| 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 |