1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/gl/GrGpuGL.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,464 @@ 1.4 +/* 1.5 + * Copyright 2011 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#ifndef GrGpuGL_DEFINED 1.12 +#define GrGpuGL_DEFINED 1.13 + 1.14 +#include "GrBinHashKey.h" 1.15 +#include "GrDrawState.h" 1.16 +#include "GrGLContext.h" 1.17 +#include "GrGLIRect.h" 1.18 +#include "GrGLIndexBuffer.h" 1.19 +#include "GrGLProgram.h" 1.20 +#include "GrGLStencilBuffer.h" 1.21 +#include "GrGLTexture.h" 1.22 +#include "GrGLVertexArray.h" 1.23 +#include "GrGLVertexBuffer.h" 1.24 +#include "GrGpu.h" 1.25 +#include "GrTHashTable.h" 1.26 +#include "SkTypes.h" 1.27 + 1.28 +#ifdef SK_DEVELOPER 1.29 +#define PROGRAM_CACHE_STATS 1.30 +#endif 1.31 + 1.32 +class GrGpuGL : public GrGpu { 1.33 +public: 1.34 + GrGpuGL(const GrGLContext& ctx, GrContext* context); 1.35 + virtual ~GrGpuGL(); 1.36 + 1.37 + const GrGLContext& glContext() const { return fGLContext; } 1.38 + 1.39 + const GrGLInterface* glInterface() const { return fGLContext.interface(); } 1.40 + const GrGLContextInfo& ctxInfo() const { return fGLContext; } 1.41 + GrGLStandard glStandard() const { return fGLContext.standard(); } 1.42 + GrGLVersion glVersion() const { return fGLContext.version(); } 1.43 + GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); } 1.44 + const GrGLCaps& glCaps() const { return *fGLContext.caps(); } 1.45 + 1.46 + // Used by GrGLProgram and GrGLTexGenProgramEffects to configure OpenGL state. 1.47 + void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture); 1.48 + void setProjectionMatrix(const SkMatrix& matrix, 1.49 + const SkISize& renderTargetSize, 1.50 + GrSurfaceOrigin renderTargetOrigin); 1.51 + enum TexGenComponents { 1.52 + kS_TexGenComponents = 1, 1.53 + kST_TexGenComponents = 2, 1.54 + kSTR_TexGenComponents = 3 1.55 + }; 1.56 + void enableTexGen(int unitIdx, TexGenComponents, const GrGLfloat* coefficients); 1.57 + void enableTexGen(int unitIdx, TexGenComponents, const SkMatrix& matrix); 1.58 + void flushTexGenSettings(int numUsedTexCoordSets); 1.59 + bool shouldUseFixedFunctionTexturing() const { 1.60 + return this->glCaps().fixedFunctionSupport() && 1.61 + this->glCaps().pathRenderingSupport(); 1.62 + } 1.63 + 1.64 + bool programUnitTest(int maxStages); 1.65 + 1.66 + // GrGpu overrides 1.67 + virtual GrPixelConfig preferredReadPixelsConfig(GrPixelConfig readConfig, 1.68 + GrPixelConfig surfaceConfig) const SK_OVERRIDE; 1.69 + virtual GrPixelConfig preferredWritePixelsConfig(GrPixelConfig writeConfig, 1.70 + GrPixelConfig surfaceConfig) const SK_OVERRIDE; 1.71 + virtual bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const SK_OVERRIDE; 1.72 + virtual bool readPixelsWillPayForYFlip( 1.73 + GrRenderTarget* renderTarget, 1.74 + int left, int top, 1.75 + int width, int height, 1.76 + GrPixelConfig config, 1.77 + size_t rowBytes) const SK_OVERRIDE; 1.78 + virtual bool fullReadPixelsIsFasterThanPartial() const SK_OVERRIDE; 1.79 + 1.80 + virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE; 1.81 + 1.82 + virtual void abandonResources() SK_OVERRIDE; 1.83 + 1.84 + // These functions should be used to bind GL objects. They track the GL state and skip redundant 1.85 + // bindings. Making the equivalent glBind calls directly will confuse the state tracking. 1.86 + void bindVertexArray(GrGLuint id) { 1.87 + fHWGeometryState.setVertexArrayID(this, id); 1.88 + } 1.89 + void bindIndexBufferAndDefaultVertexArray(GrGLuint id) { 1.90 + fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, id); 1.91 + } 1.92 + void bindVertexBuffer(GrGLuint id) { 1.93 + fHWGeometryState.setVertexBufferID(this, id); 1.94 + } 1.95 + 1.96 + // These callbacks update state tracking when GL objects are deleted. They are called from 1.97 + // GrGLResource onRelease functions. 1.98 + void notifyVertexArrayDelete(GrGLuint id) { 1.99 + fHWGeometryState.notifyVertexArrayDelete(id); 1.100 + } 1.101 + void notifyVertexBufferDelete(GrGLuint id) { 1.102 + fHWGeometryState.notifyVertexBufferDelete(id); 1.103 + } 1.104 + void notifyIndexBufferDelete(GrGLuint id) { 1.105 + fHWGeometryState.notifyIndexBufferDelete(id); 1.106 + } 1.107 + void notifyTextureDelete(GrGLTexture* texture); 1.108 + void notifyRenderTargetDelete(GrRenderTarget* renderTarget); 1.109 + 1.110 +protected: 1.111 + virtual bool onCopySurface(GrSurface* dst, 1.112 + GrSurface* src, 1.113 + const SkIRect& srcRect, 1.114 + const SkIPoint& dstPoint) SK_OVERRIDE; 1.115 + 1.116 + virtual bool onCanCopySurface(GrSurface* dst, 1.117 + GrSurface* src, 1.118 + const SkIRect& srcRect, 1.119 + const SkIPoint& dstPoint) SK_OVERRIDE; 1.120 + 1.121 +private: 1.122 + // GrGpu overrides 1.123 + virtual void onResetContext(uint32_t resetBits) SK_OVERRIDE; 1.124 + 1.125 + virtual GrTexture* onCreateTexture(const GrTextureDesc& desc, 1.126 + const void* srcData, 1.127 + size_t rowBytes) SK_OVERRIDE; 1.128 + virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) SK_OVERRIDE; 1.129 + virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) SK_OVERRIDE; 1.130 + virtual GrPath* onCreatePath(const SkPath&, const SkStrokeRec&) SK_OVERRIDE; 1.131 + virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) SK_OVERRIDE; 1.132 + virtual GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) SK_OVERRIDE; 1.133 + virtual bool createStencilBufferForRenderTarget(GrRenderTarget* rt, 1.134 + int width, 1.135 + int height) SK_OVERRIDE; 1.136 + virtual bool attachStencilBufferToRenderTarget( 1.137 + GrStencilBuffer* sb, 1.138 + GrRenderTarget* rt) SK_OVERRIDE; 1.139 + 1.140 + virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect) SK_OVERRIDE; 1.141 + 1.142 + virtual void onForceRenderTargetFlush() SK_OVERRIDE; 1.143 + 1.144 + virtual bool onReadPixels(GrRenderTarget* target, 1.145 + int left, int top, 1.146 + int width, int height, 1.147 + GrPixelConfig, 1.148 + void* buffer, 1.149 + size_t rowBytes) SK_OVERRIDE; 1.150 + 1.151 + virtual bool onWriteTexturePixels(GrTexture* texture, 1.152 + int left, int top, int width, int height, 1.153 + GrPixelConfig config, const void* buffer, 1.154 + size_t rowBytes) SK_OVERRIDE; 1.155 + 1.156 + virtual void onResolveRenderTarget(GrRenderTarget* target) SK_OVERRIDE; 1.157 + 1.158 + virtual void onGpuDraw(const DrawInfo&) SK_OVERRIDE; 1.159 + 1.160 + virtual void onGpuStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE; 1.161 + virtual void onGpuDrawPath(const GrPath*, SkPath::FillType) SK_OVERRIDE; 1.162 + 1.163 + virtual void clearStencil() SK_OVERRIDE; 1.164 + virtual void clearStencilClip(const SkIRect& rect, 1.165 + bool insideClip) SK_OVERRIDE; 1.166 + virtual bool flushGraphicsState(DrawType, const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE; 1.167 + 1.168 + // GrDrawTarget ovverides 1.169 + virtual void onInstantGpuTraceEvent(const char* marker) SK_OVERRIDE; 1.170 + virtual void onPushGpuTraceEvent(const char* marker) SK_OVERRIDE; 1.171 + virtual void onPopGpuTraceEvent() SK_OVERRIDE; 1.172 + 1.173 + 1.174 + // binds texture unit in GL 1.175 + void setTextureUnit(int unitIdx); 1.176 + 1.177 + // Sets up vertex attribute pointers and strides. On return indexOffsetInBytes gives the offset 1.178 + // an into the index buffer. It does not account for drawInfo.startIndex() but rather the start 1.179 + // index is relative to the returned offset. 1.180 + void setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes); 1.181 + 1.182 + // Subclasses should call this to flush the blend state. 1.183 + // The params should be the final coefficients to apply 1.184 + // (after any blending optimizations or dual source blending considerations 1.185 + // have been accounted for). 1.186 + void flushBlend(bool isLines, GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff); 1.187 + 1.188 + bool hasExtension(const char* ext) const { return fGLContext.hasExtension(ext); } 1.189 + 1.190 + static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff); 1.191 + 1.192 + class ProgramCache : public ::SkNoncopyable { 1.193 + public: 1.194 + ProgramCache(GrGpuGL* gpu); 1.195 + ~ProgramCache(); 1.196 + 1.197 + void abandon(); 1.198 + GrGLProgram* getProgram(const GrGLProgramDesc& desc, 1.199 + const GrEffectStage* colorStages[], 1.200 + const GrEffectStage* coverageStages[]); 1.201 + 1.202 + private: 1.203 + enum { 1.204 + // We may actually have kMaxEntries+1 shaders in the GL context because we create a new 1.205 + // shader before evicting from the cache. 1.206 + kMaxEntries = 32, 1.207 + kHashBits = 6, 1.208 + }; 1.209 + 1.210 + struct Entry; 1.211 + 1.212 + struct ProgDescLess; 1.213 + 1.214 + // binary search for entry matching desc. returns index into fEntries that matches desc or ~ 1.215 + // of the index of where it should be inserted. 1.216 + int search(const GrGLProgramDesc& desc) const; 1.217 + 1.218 + // sorted array of all the entries 1.219 + Entry* fEntries[kMaxEntries]; 1.220 + // hash table based on lowest kHashBits bits of the program key. Used to avoid binary 1.221 + // searching fEntries. 1.222 + Entry* fHashTable[1 << kHashBits]; 1.223 + 1.224 + int fCount; 1.225 + unsigned int fCurrLRUStamp; 1.226 + GrGpuGL* fGpu; 1.227 +#ifdef PROGRAM_CACHE_STATS 1.228 + int fTotalRequests; 1.229 + int fCacheMisses; 1.230 + int fHashMisses; // cache hit but hash table missed 1.231 +#endif 1.232 + }; 1.233 + 1.234 + // flushes dithering, color-mask, and face culling stat 1.235 + void flushMiscFixedFunctionState(); 1.236 + 1.237 + // flushes the scissor. see the note on flushBoundTextureAndParams about 1.238 + // flushing the scissor after that function is called. 1.239 + void flushScissor(); 1.240 + 1.241 + void initFSAASupport(); 1.242 + 1.243 + // determines valid stencil formats 1.244 + void initStencilFormats(); 1.245 + 1.246 + // sets a texture unit to use for texture operations other than binding a texture to a program. 1.247 + // ensures that such operations don't negatively interact with tracking bound textures. 1.248 + void setScratchTextureUnit(); 1.249 + 1.250 + // bound is region that may be modified and therefore has to be resolved. 1.251 + // NULL means whole target. Can be an empty rect. 1.252 + void flushRenderTarget(const SkIRect* bound); 1.253 + void flushStencil(DrawType); 1.254 + void flushAAState(DrawType); 1.255 + void flushPathStencilSettings(SkPath::FillType fill); 1.256 + 1.257 + bool configToGLFormats(GrPixelConfig config, 1.258 + bool getSizedInternal, 1.259 + GrGLenum* internalFormat, 1.260 + GrGLenum* externalFormat, 1.261 + GrGLenum* externalType); 1.262 + // helper for onCreateTexture and writeTexturePixels 1.263 + bool uploadTexData(const GrGLTexture::Desc& desc, 1.264 + bool isNewTexture, 1.265 + int left, int top, int width, int height, 1.266 + GrPixelConfig dataConfig, 1.267 + const void* data, 1.268 + size_t rowBytes); 1.269 + 1.270 + bool createRenderTargetObjects(int width, int height, 1.271 + GrGLuint texID, 1.272 + GrGLRenderTarget::Desc* desc); 1.273 + 1.274 + GrGLContext fGLContext; 1.275 + 1.276 + // GL program-related state 1.277 + ProgramCache* fProgramCache; 1.278 + SkAutoTUnref<GrGLProgram> fCurrentProgram; 1.279 + 1.280 + /////////////////////////////////////////////////////////////////////////// 1.281 + ///@name Caching of GL State 1.282 + ///@{ 1.283 + int fHWActiveTextureUnitIdx; 1.284 + GrGLuint fHWProgramID; 1.285 + 1.286 + GrGLProgram::SharedGLState fSharedGLProgramState; 1.287 + 1.288 + enum TriState { 1.289 + kNo_TriState, 1.290 + kYes_TriState, 1.291 + kUnknown_TriState 1.292 + }; 1.293 + 1.294 + // last scissor / viewport scissor state seen by the GL. 1.295 + struct { 1.296 + TriState fEnabled; 1.297 + GrGLIRect fRect; 1.298 + void invalidate() { 1.299 + fEnabled = kUnknown_TriState; 1.300 + fRect.invalidate(); 1.301 + } 1.302 + } fHWScissorSettings; 1.303 + 1.304 + GrGLIRect fHWViewport; 1.305 + 1.306 + /** 1.307 + * Tracks bound vertex and index buffers and vertex attrib array state. 1.308 + */ 1.309 + class HWGeometryState { 1.310 + public: 1.311 + HWGeometryState() { fVBOVertexArray = NULL; this->invalidate(); } 1.312 + 1.313 + ~HWGeometryState() { SkSafeUnref(fVBOVertexArray); } 1.314 + 1.315 + void invalidate() { 1.316 + fBoundVertexArrayIDIsValid = false; 1.317 + fBoundVertexBufferIDIsValid = false; 1.318 + fDefaultVertexArrayBoundIndexBufferID = false; 1.319 + fDefaultVertexArrayBoundIndexBufferIDIsValid = false; 1.320 + fDefaultVertexArrayAttribState.invalidate(); 1.321 + if (NULL != fVBOVertexArray) { 1.322 + fVBOVertexArray->invalidateCachedState(); 1.323 + } 1.324 + } 1.325 + 1.326 + void notifyVertexArrayDelete(GrGLuint id) { 1.327 + if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) { 1.328 + // Does implicit bind to 0 1.329 + fBoundVertexArrayID = 0; 1.330 + } 1.331 + } 1.332 + 1.333 + void setVertexArrayID(GrGpuGL* gpu, GrGLuint arrayID) { 1.334 + if (!gpu->glCaps().vertexArrayObjectSupport()) { 1.335 + SkASSERT(0 == arrayID); 1.336 + return; 1.337 + } 1.338 + if (!fBoundVertexArrayIDIsValid || arrayID != fBoundVertexArrayID) { 1.339 + GR_GL_CALL(gpu->glInterface(), BindVertexArray(arrayID)); 1.340 + fBoundVertexArrayIDIsValid = true; 1.341 + fBoundVertexArrayID = arrayID; 1.342 + } 1.343 + } 1.344 + 1.345 + void notifyVertexBufferDelete(GrGLuint id) { 1.346 + if (fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID) { 1.347 + fBoundVertexBufferID = 0; 1.348 + } 1.349 + if (NULL != fVBOVertexArray) { 1.350 + fVBOVertexArray->notifyVertexBufferDelete(id); 1.351 + } 1.352 + fDefaultVertexArrayAttribState.notifyVertexBufferDelete(id); 1.353 + } 1.354 + 1.355 + void notifyIndexBufferDelete(GrGLuint id) { 1.356 + if (fDefaultVertexArrayBoundIndexBufferIDIsValid && 1.357 + id == fDefaultVertexArrayBoundIndexBufferID) { 1.358 + fDefaultVertexArrayBoundIndexBufferID = 0; 1.359 + } 1.360 + if (NULL != fVBOVertexArray) { 1.361 + fVBOVertexArray->notifyIndexBufferDelete(id); 1.362 + } 1.363 + } 1.364 + 1.365 + void setVertexBufferID(GrGpuGL* gpu, GrGLuint id) { 1.366 + if (!fBoundVertexBufferIDIsValid || id != fBoundVertexBufferID) { 1.367 + GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ARRAY_BUFFER, id)); 1.368 + fBoundVertexBufferIDIsValid = true; 1.369 + fBoundVertexBufferID = id; 1.370 + } 1.371 + } 1.372 + 1.373 + /** 1.374 + * Binds the default vertex array and binds the index buffer. This is used when binding 1.375 + * an index buffer in order to update it. 1.376 + */ 1.377 + void setIndexBufferIDOnDefaultVertexArray(GrGpuGL* gpu, GrGLuint id) { 1.378 + this->setVertexArrayID(gpu, 0); 1.379 + if (!fDefaultVertexArrayBoundIndexBufferIDIsValid || 1.380 + id != fDefaultVertexArrayBoundIndexBufferID) { 1.381 + GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id)); 1.382 + fDefaultVertexArrayBoundIndexBufferIDIsValid = true; 1.383 + fDefaultVertexArrayBoundIndexBufferID = id; 1.384 + } 1.385 + } 1.386 + 1.387 + /** 1.388 + * Binds the vertex array object that should be used to render from the vertex buffer. 1.389 + * The vertex array is bound and its attrib array state object is returned. The vertex 1.390 + * buffer is bound. The index buffer (if non-NULL) is bound to the vertex array. The 1.391 + * returned GrGLAttribArrayState should be used to set vertex attribute arrays. 1.392 + */ 1.393 + GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGpuGL* gpu, 1.394 + const GrGLVertexBuffer* vbuffer, 1.395 + const GrGLIndexBuffer* ibuffer); 1.396 + 1.397 + private: 1.398 + GrGLuint fBoundVertexArrayID; 1.399 + GrGLuint fBoundVertexBufferID; 1.400 + bool fBoundVertexArrayIDIsValid; 1.401 + bool fBoundVertexBufferIDIsValid; 1.402 + 1.403 + GrGLuint fDefaultVertexArrayBoundIndexBufferID; 1.404 + bool fDefaultVertexArrayBoundIndexBufferIDIsValid; 1.405 + // We return a non-const pointer to this from bindArrayAndBuffersToDraw when vertex array 0 1.406 + // is bound. However, this class is internal to GrGpuGL and this object never leaks out of 1.407 + // GrGpuGL. 1.408 + GrGLAttribArrayState fDefaultVertexArrayAttribState; 1.409 + 1.410 + // This is used when we're using a core profile and the vertices are in a VBO. 1.411 + GrGLVertexArray* fVBOVertexArray; 1.412 + } fHWGeometryState; 1.413 + 1.414 + struct { 1.415 + GrBlendCoeff fSrcCoeff; 1.416 + GrBlendCoeff fDstCoeff; 1.417 + GrColor fConstColor; 1.418 + bool fConstColorValid; 1.419 + TriState fEnabled; 1.420 + 1.421 + void invalidate() { 1.422 + fSrcCoeff = kInvalid_GrBlendCoeff; 1.423 + fDstCoeff = kInvalid_GrBlendCoeff; 1.424 + fConstColorValid = false; 1.425 + fEnabled = kUnknown_TriState; 1.426 + } 1.427 + } fHWBlendState; 1.428 + 1.429 + struct { 1.430 + TriState fMSAAEnabled; 1.431 + TriState fSmoothLineEnabled; 1.432 + void invalidate() { 1.433 + fMSAAEnabled = kUnknown_TriState; 1.434 + fSmoothLineEnabled = kUnknown_TriState; 1.435 + } 1.436 + } fHWAAState; 1.437 + 1.438 + 1.439 + GrGLProgram::MatrixState fHWProjectionMatrixState; 1.440 + 1.441 + GrStencilSettings fHWStencilSettings; 1.442 + TriState fHWStencilTestEnabled; 1.443 + GrStencilSettings fHWPathStencilSettings; 1.444 + 1.445 + GrDrawState::DrawFace fHWDrawFace; 1.446 + TriState fHWWriteToColor; 1.447 + TriState fHWDitherEnabled; 1.448 + GrRenderTarget* fHWBoundRenderTarget; 1.449 + SkTArray<GrTexture*, true> fHWBoundTextures; 1.450 + 1.451 + struct TexGenData { 1.452 + GrGLenum fMode; 1.453 + GrGLint fNumComponents; 1.454 + GrGLfloat fCoefficients[3 * 3]; 1.455 + }; 1.456 + int fHWActiveTexGenSets; 1.457 + SkTArray<TexGenData, true> fHWTexGenSettings; 1.458 + ///@} 1.459 + 1.460 + // we record what stencil format worked last time to hopefully exit early 1.461 + // from our loop that tries stencil formats and calls check fb status. 1.462 + int fLastSuccessfulStencilFmtIdx; 1.463 + 1.464 + typedef GrGpu INHERITED; 1.465 +}; 1.466 + 1.467 +#endif