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