1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrGpuGL_DEFINED 9 #define GrGpuGL_DEFINED 10 11 #include "GrBinHashKey.h" 12 #include "GrDrawState.h" 13 #include "GrGLContext.h" 14 #include "GrGLIRect.h" 15 #include "GrGLIndexBuffer.h" 16 #include "GrGLProgram.h" 17 #include "GrGLStencilBuffer.h" 18 #include "GrGLTexture.h" 19 #include "GrGLVertexArray.h" 20 #include "GrGLVertexBuffer.h" 21 #include "GrGpu.h" 22 #include "GrTHashTable.h" 23 #include "SkTypes.h" 24 25 #ifdef SK_DEVELOPER 26 #define PROGRAM_CACHE_STATS 27 #endif 28 29 class GrGLNameAllocator; 30 31 class GrGpuGL : public GrGpu { 32 public: 33 GrGpuGL(const GrGLContext& ctx, GrContext* context); 34 virtual ~GrGpuGL(); 35 glContext()36 const GrGLContext& glContext() const { return fGLContext; } 37 glInterface()38 const GrGLInterface* glInterface() const { return fGLContext.interface(); } ctxInfo()39 const GrGLContextInfo& ctxInfo() const { return fGLContext; } glStandard()40 GrGLStandard glStandard() const { return fGLContext.standard(); } glVersion()41 GrGLVersion glVersion() const { return fGLContext.version(); } glslGeneration()42 GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); } glCaps()43 const GrGLCaps& glCaps() const { return *fGLContext.caps(); } 44 45 virtual void discard(GrRenderTarget*) SK_OVERRIDE; 46 47 // Used by GrGLProgram and GrGLPathTexGenProgramEffects to configure OpenGL 48 // state. 49 void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture); 50 void setProjectionMatrix(const SkMatrix& matrix, 51 const SkISize& renderTargetSize, 52 GrSurfaceOrigin renderTargetOrigin); 53 enum PathTexGenComponents { 54 kS_PathTexGenComponents = 1, 55 kST_PathTexGenComponents = 2, 56 kSTR_PathTexGenComponents = 3 57 }; 58 void enablePathTexGen(int unitIdx, PathTexGenComponents, const GrGLfloat* coefficients); 59 void enablePathTexGen(int unitIdx, PathTexGenComponents, const SkMatrix& matrix); 60 void flushPathTexGenSettings(int numUsedTexCoordSets); shouldUseFixedFunctionTexturing()61 bool shouldUseFixedFunctionTexturing() const { 62 return this->glCaps().pathRenderingSupport(); 63 } 64 65 bool programUnitTest(int maxStages); 66 67 // GrGpu overrides 68 virtual GrPixelConfig preferredReadPixelsConfig(GrPixelConfig readConfig, 69 GrPixelConfig surfaceConfig) const SK_OVERRIDE; 70 virtual GrPixelConfig preferredWritePixelsConfig(GrPixelConfig writeConfig, 71 GrPixelConfig surfaceConfig) const SK_OVERRIDE; 72 virtual bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const SK_OVERRIDE; 73 virtual bool readPixelsWillPayForYFlip( 74 GrRenderTarget* renderTarget, 75 int left, int top, 76 int width, int height, 77 GrPixelConfig config, 78 size_t rowBytes) const SK_OVERRIDE; 79 virtual bool fullReadPixelsIsFasterThanPartial() const SK_OVERRIDE; 80 81 virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE; 82 83 virtual void abandonResources() SK_OVERRIDE; 84 85 // These functions should be used to bind GL objects. They track the GL state and skip redundant 86 // bindings. Making the equivalent glBind calls directly will confuse the state tracking. bindVertexArray(GrGLuint id)87 void bindVertexArray(GrGLuint id) { 88 fHWGeometryState.setVertexArrayID(this, id); 89 } bindIndexBufferAndDefaultVertexArray(GrGLuint id)90 void bindIndexBufferAndDefaultVertexArray(GrGLuint id) { 91 fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, id); 92 } bindVertexBuffer(GrGLuint id)93 void bindVertexBuffer(GrGLuint id) { 94 fHWGeometryState.setVertexBufferID(this, id); 95 } 96 97 // These callbacks update state tracking when GL objects are deleted. They are called from 98 // GrGLResource onRelease functions. notifyVertexArrayDelete(GrGLuint id)99 void notifyVertexArrayDelete(GrGLuint id) { 100 fHWGeometryState.notifyVertexArrayDelete(id); 101 } notifyVertexBufferDelete(GrGLuint id)102 void notifyVertexBufferDelete(GrGLuint id) { 103 fHWGeometryState.notifyVertexBufferDelete(id); 104 } notifyIndexBufferDelete(GrGLuint id)105 void notifyIndexBufferDelete(GrGLuint id) { 106 fHWGeometryState.notifyIndexBufferDelete(id); 107 } 108 void notifyTextureDelete(GrGLTexture* texture); 109 void notifyRenderTargetDelete(GrRenderTarget* renderTarget); 110 111 // These functions should be used to generate and delete GL path names. They have their own 112 // allocator that runs on the client side, so they are much faster than going through GenPaths. 113 GrGLuint createGLPathObject(); 114 void deleteGLPathObject(GrGLuint); 115 116 protected: 117 virtual bool onCopySurface(GrSurface* dst, 118 GrSurface* src, 119 const SkIRect& srcRect, 120 const SkIPoint& dstPoint) SK_OVERRIDE; 121 122 virtual bool onCanCopySurface(GrSurface* dst, 123 GrSurface* src, 124 const SkIRect& srcRect, 125 const SkIPoint& dstPoint) SK_OVERRIDE; 126 127 private: 128 // GrGpu overrides 129 virtual void onResetContext(uint32_t resetBits) SK_OVERRIDE; 130 131 virtual GrTexture* onCreateTexture(const GrTextureDesc& desc, 132 const void* srcData, 133 size_t rowBytes) SK_OVERRIDE; 134 virtual GrTexture* onCreateCompressedTexture(const GrTextureDesc& desc, 135 const void* srcData) SK_OVERRIDE; 136 virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) SK_OVERRIDE; 137 virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) SK_OVERRIDE; 138 virtual GrPath* onCreatePath(const SkPath&, const SkStrokeRec&) SK_OVERRIDE; 139 virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) SK_OVERRIDE; 140 virtual GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) SK_OVERRIDE; 141 virtual bool createStencilBufferForRenderTarget(GrRenderTarget* rt, 142 int width, 143 int height) SK_OVERRIDE; 144 virtual bool attachStencilBufferToRenderTarget( 145 GrStencilBuffer* sb, 146 GrRenderTarget* rt) SK_OVERRIDE; 147 148 virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect) SK_OVERRIDE; 149 150 virtual bool onReadPixels(GrRenderTarget* target, 151 int left, int top, 152 int width, int height, 153 GrPixelConfig, 154 void* buffer, 155 size_t rowBytes) SK_OVERRIDE; 156 157 virtual bool onWriteTexturePixels(GrTexture* texture, 158 int left, int top, int width, int height, 159 GrPixelConfig config, const void* buffer, 160 size_t rowBytes) SK_OVERRIDE; 161 162 virtual void onResolveRenderTarget(GrRenderTarget* target) SK_OVERRIDE; 163 164 virtual void onGpuDraw(const DrawInfo&) SK_OVERRIDE; 165 166 virtual void onGpuStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE; 167 virtual void onGpuDrawPath(const GrPath*, SkPath::FillType) SK_OVERRIDE; 168 virtual void onGpuDrawPaths(int, const GrPath**, const SkMatrix*, 169 SkPath::FillType, 170 SkStrokeRec::Style) SK_OVERRIDE; 171 172 virtual void clearStencil() SK_OVERRIDE; 173 virtual void clearStencilClip(const SkIRect& rect, 174 bool insideClip) SK_OVERRIDE; 175 virtual bool flushGraphicsState(DrawType, const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE; 176 177 // GrDrawTarget ovverides 178 virtual void didAddGpuTraceMarker() SK_OVERRIDE; 179 virtual void didRemoveGpuTraceMarker() SK_OVERRIDE; 180 181 // binds texture unit in GL 182 void setTextureUnit(int unitIdx); 183 184 // Sets up vertex attribute pointers and strides. On return indexOffsetInBytes gives the offset 185 // an into the index buffer. It does not account for drawInfo.startIndex() but rather the start 186 // index is relative to the returned offset. 187 void setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes); 188 189 // Subclasses should call this to flush the blend state. 190 // The params should be the final coefficients to apply 191 // (after any blending optimizations or dual source blending considerations 192 // have been accounted for). 193 void flushBlend(bool isLines, GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff); 194 hasExtension(const char * ext)195 bool hasExtension(const char* ext) const { return fGLContext.hasExtension(ext); } 196 197 static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff); 198 199 class ProgramCache : public ::SkNoncopyable { 200 public: 201 ProgramCache(GrGpuGL* gpu); 202 ~ProgramCache(); 203 204 void abandon(); 205 GrGLProgram* getProgram(const GrGLProgramDesc& desc, 206 const GrEffectStage* colorStages[], 207 const GrEffectStage* coverageStages[]); 208 209 private: 210 enum { 211 // We may actually have kMaxEntries+1 shaders in the GL context because we create a new 212 // shader before evicting from the cache. 213 kMaxEntries = 128, 214 kHashBits = 6, 215 }; 216 217 struct Entry; 218 219 struct ProgDescLess; 220 221 // binary search for entry matching desc. returns index into fEntries that matches desc or ~ 222 // of the index of where it should be inserted. 223 int search(const GrGLProgramDesc& desc) const; 224 225 // sorted array of all the entries 226 Entry* fEntries[kMaxEntries]; 227 // hash table based on lowest kHashBits bits of the program key. Used to avoid binary 228 // searching fEntries. 229 Entry* fHashTable[1 << kHashBits]; 230 231 int fCount; 232 unsigned int fCurrLRUStamp; 233 GrGpuGL* fGpu; 234 #ifdef PROGRAM_CACHE_STATS 235 int fTotalRequests; 236 int fCacheMisses; 237 int fHashMisses; // cache hit but hash table missed 238 #endif 239 }; 240 241 // flushes dithering, color-mask, and face culling stat 242 void flushMiscFixedFunctionState(); 243 244 // flushes the scissor. see the note on flushBoundTextureAndParams about 245 // flushing the scissor after that function is called. 246 void flushScissor(); 247 248 void initFSAASupport(); 249 250 // determines valid stencil formats 251 void initStencilFormats(); 252 253 // sets a texture unit to use for texture operations other than binding a texture to a program. 254 // ensures that such operations don't negatively interact with tracking bound textures. 255 void setScratchTextureUnit(); 256 257 // bound is region that may be modified and therefore has to be resolved. 258 // NULL means whole target. Can be an empty rect. 259 void flushRenderTarget(const SkIRect* bound); 260 void flushStencil(DrawType); 261 void flushAAState(DrawType); 262 void flushPathStencilSettings(SkPath::FillType fill); 263 264 bool configToGLFormats(GrPixelConfig config, 265 bool getSizedInternal, 266 GrGLenum* internalFormat, 267 GrGLenum* externalFormat, 268 GrGLenum* externalType); 269 // helper for onCreateTexture and writeTexturePixels 270 bool uploadTexData(const GrGLTexture::Desc& desc, 271 bool isNewTexture, 272 int left, int top, int width, int height, 273 GrPixelConfig dataConfig, 274 const void* data, 275 size_t rowBytes); 276 277 // helper for onCreateCompressedTexture. If width and height are 278 // set to -1, then this function will use desc.fWidth and desc.fHeight 279 // for the size of the data. The isNewTexture flag should be set to true 280 // whenever a new texture needs to be created. Otherwise, we assume that 281 // the texture is already in GPU memory and that it's going to be updated 282 // with new data. 283 bool uploadCompressedTexData(const GrGLTexture::Desc& desc, 284 const void* data, 285 bool isNewTexture = true, 286 int left = 0, int top = 0, 287 int width = -1, int height = -1); 288 289 bool createRenderTargetObjects(int width, int height, 290 GrGLuint texID, 291 GrGLRenderTarget::Desc* desc); 292 293 GrGLContext fGLContext; 294 295 // GL program-related state 296 ProgramCache* fProgramCache; 297 SkAutoTUnref<GrGLProgram> fCurrentProgram; 298 299 /////////////////////////////////////////////////////////////////////////// 300 ///@name Caching of GL State 301 ///@{ 302 int fHWActiveTextureUnitIdx; 303 GrGLuint fHWProgramID; 304 305 GrGLProgram::SharedGLState fSharedGLProgramState; 306 307 enum TriState { 308 kNo_TriState, 309 kYes_TriState, 310 kUnknown_TriState 311 }; 312 313 // last scissor / viewport scissor state seen by the GL. 314 struct { 315 TriState fEnabled; 316 GrGLIRect fRect; invalidate__anon6eef22210208317 void invalidate() { 318 fEnabled = kUnknown_TriState; 319 fRect.invalidate(); 320 } 321 } fHWScissorSettings; 322 323 GrGLIRect fHWViewport; 324 325 /** 326 * Tracks bound vertex and index buffers and vertex attrib array state. 327 */ 328 class HWGeometryState { 329 public: HWGeometryState()330 HWGeometryState() { fVBOVertexArray = NULL; this->invalidate(); } 331 ~HWGeometryState()332 ~HWGeometryState() { SkSafeUnref(fVBOVertexArray); } 333 invalidate()334 void invalidate() { 335 fBoundVertexArrayIDIsValid = false; 336 fBoundVertexBufferIDIsValid = false; 337 fDefaultVertexArrayBoundIndexBufferID = false; 338 fDefaultVertexArrayBoundIndexBufferIDIsValid = false; 339 fDefaultVertexArrayAttribState.invalidate(); 340 if (NULL != fVBOVertexArray) { 341 fVBOVertexArray->invalidateCachedState(); 342 } 343 } 344 notifyVertexArrayDelete(GrGLuint id)345 void notifyVertexArrayDelete(GrGLuint id) { 346 if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) { 347 // Does implicit bind to 0 348 fBoundVertexArrayID = 0; 349 } 350 } 351 setVertexArrayID(GrGpuGL * gpu,GrGLuint arrayID)352 void setVertexArrayID(GrGpuGL* gpu, GrGLuint arrayID) { 353 if (!gpu->glCaps().vertexArrayObjectSupport()) { 354 SkASSERT(0 == arrayID); 355 return; 356 } 357 if (!fBoundVertexArrayIDIsValid || arrayID != fBoundVertexArrayID) { 358 GR_GL_CALL(gpu->glInterface(), BindVertexArray(arrayID)); 359 fBoundVertexArrayIDIsValid = true; 360 fBoundVertexArrayID = arrayID; 361 } 362 } 363 notifyVertexBufferDelete(GrGLuint id)364 void notifyVertexBufferDelete(GrGLuint id) { 365 if (fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID) { 366 fBoundVertexBufferID = 0; 367 } 368 if (NULL != fVBOVertexArray) { 369 fVBOVertexArray->notifyVertexBufferDelete(id); 370 } 371 fDefaultVertexArrayAttribState.notifyVertexBufferDelete(id); 372 } 373 notifyIndexBufferDelete(GrGLuint id)374 void notifyIndexBufferDelete(GrGLuint id) { 375 if (fDefaultVertexArrayBoundIndexBufferIDIsValid && 376 id == fDefaultVertexArrayBoundIndexBufferID) { 377 fDefaultVertexArrayBoundIndexBufferID = 0; 378 } 379 if (NULL != fVBOVertexArray) { 380 fVBOVertexArray->notifyIndexBufferDelete(id); 381 } 382 } 383 setVertexBufferID(GrGpuGL * gpu,GrGLuint id)384 void setVertexBufferID(GrGpuGL* gpu, GrGLuint id) { 385 if (!fBoundVertexBufferIDIsValid || id != fBoundVertexBufferID) { 386 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ARRAY_BUFFER, id)); 387 fBoundVertexBufferIDIsValid = true; 388 fBoundVertexBufferID = id; 389 } 390 } 391 392 /** 393 * Binds the default vertex array and binds the index buffer. This is used when binding 394 * an index buffer in order to update it. 395 */ setIndexBufferIDOnDefaultVertexArray(GrGpuGL * gpu,GrGLuint id)396 void setIndexBufferIDOnDefaultVertexArray(GrGpuGL* gpu, GrGLuint id) { 397 this->setVertexArrayID(gpu, 0); 398 if (!fDefaultVertexArrayBoundIndexBufferIDIsValid || 399 id != fDefaultVertexArrayBoundIndexBufferID) { 400 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id)); 401 fDefaultVertexArrayBoundIndexBufferIDIsValid = true; 402 fDefaultVertexArrayBoundIndexBufferID = id; 403 } 404 } 405 406 /** 407 * Binds the vertex array object that should be used to render from the vertex buffer. 408 * The vertex array is bound and its attrib array state object is returned. The vertex 409 * buffer is bound. The index buffer (if non-NULL) is bound to the vertex array. The 410 * returned GrGLAttribArrayState should be used to set vertex attribute arrays. 411 */ 412 GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGpuGL* gpu, 413 const GrGLVertexBuffer* vbuffer, 414 const GrGLIndexBuffer* ibuffer); 415 416 private: 417 GrGLuint fBoundVertexArrayID; 418 GrGLuint fBoundVertexBufferID; 419 bool fBoundVertexArrayIDIsValid; 420 bool fBoundVertexBufferIDIsValid; 421 422 GrGLuint fDefaultVertexArrayBoundIndexBufferID; 423 bool fDefaultVertexArrayBoundIndexBufferIDIsValid; 424 // We return a non-const pointer to this from bindArrayAndBuffersToDraw when vertex array 0 425 // is bound. However, this class is internal to GrGpuGL and this object never leaks out of 426 // GrGpuGL. 427 GrGLAttribArrayState fDefaultVertexArrayAttribState; 428 429 // This is used when we're using a core profile and the vertices are in a VBO. 430 GrGLVertexArray* fVBOVertexArray; 431 } fHWGeometryState; 432 433 struct { 434 GrBlendCoeff fSrcCoeff; 435 GrBlendCoeff fDstCoeff; 436 GrColor fConstColor; 437 bool fConstColorValid; 438 TriState fEnabled; 439 invalidate__anon6eef22210308440 void invalidate() { 441 fSrcCoeff = kInvalid_GrBlendCoeff; 442 fDstCoeff = kInvalid_GrBlendCoeff; 443 fConstColorValid = false; 444 fEnabled = kUnknown_TriState; 445 } 446 } fHWBlendState; 447 448 struct { 449 TriState fMSAAEnabled; 450 TriState fSmoothLineEnabled; invalidate__anon6eef22210408451 void invalidate() { 452 fMSAAEnabled = kUnknown_TriState; 453 fSmoothLineEnabled = kUnknown_TriState; 454 } 455 } fHWAAState; 456 457 458 GrGLProgram::MatrixState fHWProjectionMatrixState; 459 460 GrStencilSettings fHWStencilSettings; 461 TriState fHWStencilTestEnabled; 462 GrStencilSettings fHWPathStencilSettings; 463 464 GrDrawState::DrawFace fHWDrawFace; 465 TriState fHWWriteToColor; 466 TriState fHWDitherEnabled; 467 GrRenderTarget* fHWBoundRenderTarget; 468 SkTArray<GrTexture*, true> fHWBoundTextures; 469 470 struct PathTexGenData { 471 GrGLenum fMode; 472 GrGLint fNumComponents; 473 GrGLfloat fCoefficients[3 * 3]; 474 }; 475 int fHWActivePathTexGenSets; 476 SkTArray<PathTexGenData, true> fHWPathTexGenSettings; 477 ///@} 478 479 // we record what stencil format worked last time to hopefully exit early 480 // from our loop that tries stencil formats and calls check fb status. 481 int fLastSuccessfulStencilFmtIdx; 482 483 SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator; 484 485 typedef GrGpu INHERITED; 486 }; 487 488 #endif 489