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