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
29class GrGLNameAllocator;
30
31class GrGpuGL : public GrGpu {
32public:
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
116protected:
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
127private:
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