• 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 "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 
glContext()35     const GrGLContext& glContext() const { return fGLContext; }
36 
glInterface()37     const GrGLInterface* glInterface() const { return fGLContext.interface(); }
ctxInfo()38     const GrGLContextInfo& ctxInfo() const { return fGLContext; }
glStandard()39     GrGLStandard glStandard() const { return fGLContext.standard(); }
glVersion()40     GrGLVersion glVersion() const { return fGLContext.version(); }
glslGeneration()41     GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); }
glCaps()42     const GrGLCaps& glCaps() const { return *fGLContext.caps(); }
43 
glPathRendering()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.
bindVertexArray(GrGLuint id)75     void bindVertexArray(GrGLuint id) {
76         fHWGeometryState.setVertexArrayID(this, id);
77     }
bindIndexBufferAndDefaultVertexArray(GrGLuint id)78     void bindIndexBufferAndDefaultVertexArray(GrGLuint id) {
79         fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, id);
80     }
bindVertexBuffer(GrGLuint id)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.
notifyVertexArrayDelete(GrGLuint id)87     void notifyVertexArrayDelete(GrGLuint id) {
88         fHWGeometryState.notifyVertexArrayDelete(id);
89     }
notifyVertexBufferDelete(GrGLuint id)90     void notifyVertexBufferDelete(GrGLuint id) {
91         fHWGeometryState.notifyVertexBufferDelete(id);
92     }
notifyIndexBufferDelete(GrGLuint id)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 
hasExtension(const char * ext)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;
invalidate__anon7c7440540208297         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:
HWGeometryState()310         HWGeometryState() { fVBOVertexArray = NULL; this->invalidate(); }
311 
~HWGeometryState()312         ~HWGeometryState() { SkSafeUnref(fVBOVertexArray); }
313 
invalidate()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 
notifyVertexArrayDelete(GrGLuint id)325         void notifyVertexArrayDelete(GrGLuint id) {
326             if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) {
327                 // Does implicit bind to 0
328                 fBoundVertexArrayID = 0;
329             }
330         }
331 
setVertexArrayID(GrGpuGL * gpu,GrGLuint arrayID)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 
notifyVertexBufferDelete(GrGLuint id)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 
notifyIndexBufferDelete(GrGLuint id)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 
setVertexBufferID(GrGpuGL * gpu,GrGLuint id)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          */
setIndexBufferIDOnDefaultVertexArray(GrGpuGL * gpu,GrGLuint id)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 
invalidate__anon7c7440540308420         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