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