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