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