• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
glContext()36     const GrGLContext& glContext() const { return fGLContext; }
37 
glInterface()38     const GrGLInterface* glInterface() const { return fGLContext.interface(); }
ctxInfo()39     const GrGLContextInfo& ctxInfo() const { return fGLContext; }
glStandard()40     GrGLStandard glStandard() const { return fGLContext.standard(); }
glVersion()41     GrGLVersion glVersion() const { return fGLContext.version(); }
glslGeneration()42     GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); }
glCaps()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);
shouldUseFixedFunctionTexturing()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.
bindVertexArray(GrGLuint id)87     void bindVertexArray(GrGLuint id) {
88         fHWGeometryState.setVertexArrayID(this, id);
89     }
bindIndexBufferAndDefaultVertexArray(GrGLuint id)90     void bindIndexBufferAndDefaultVertexArray(GrGLuint id) {
91         fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, id);
92     }
bindVertexBuffer(GrGLuint id)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.
notifyVertexArrayDelete(GrGLuint id)99     void notifyVertexArrayDelete(GrGLuint id) {
100         fHWGeometryState.notifyVertexArrayDelete(id);
101     }
notifyVertexBufferDelete(GrGLuint id)102     void notifyVertexBufferDelete(GrGLuint id) {
103         fHWGeometryState.notifyVertexBufferDelete(id);
104     }
notifyIndexBufferDelete(GrGLuint id)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 
hasExtension(const char * ext)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;
invalidate__anon6eef22210208317         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:
HWGeometryState()330         HWGeometryState() { fVBOVertexArray = NULL; this->invalidate(); }
331 
~HWGeometryState()332         ~HWGeometryState() { SkSafeUnref(fVBOVertexArray); }
333 
invalidate()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 
notifyVertexArrayDelete(GrGLuint id)345         void notifyVertexArrayDelete(GrGLuint id) {
346             if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) {
347                 // Does implicit bind to 0
348                 fBoundVertexArrayID = 0;
349             }
350         }
351 
setVertexArrayID(GrGpuGL * gpu,GrGLuint arrayID)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 
notifyVertexBufferDelete(GrGLuint id)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 
notifyIndexBufferDelete(GrGLuint id)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 
setVertexBufferID(GrGpuGL * gpu,GrGLuint id)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          */
setIndexBufferIDOnDefaultVertexArray(GrGpuGL * gpu,GrGLuint id)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 
invalidate__anon6eef22210308440         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;
invalidate__anon6eef22210408451         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