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