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