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 GrGLGpu_DEFINED
9 #define GrGLGpu_DEFINED
10 
11 #include "GrGLContext.h"
12 #include "GrGLIRect.h"
13 #include "GrGLIndexBuffer.h"
14 #include "GrGLPathRendering.h"
15 #include "GrGLProgram.h"
16 #include "GrGLRenderTarget.h"
17 #include "GrGLStencilAttachment.h"
18 #include "GrGLTexture.h"
19 #include "GrGLVertexArray.h"
20 #include "GrGLVertexBuffer.h"
21 #include "GrGpu.h"
22 #include "GrPipelineBuilder.h"
23 #include "GrXferProcessor.h"
24 #include "SkTypes.h"
25 
26 class GrPipeline;
27 class GrNonInstancedVertices;
28 
29 #ifdef SK_DEVELOPER
30 #define PROGRAM_CACHE_STATS
31 #endif
32 
33 class GrGLGpu : public GrGpu {
34 public:
35     GrGLGpu(const GrGLContext& ctx, GrContext* context);
36     ~GrGLGpu() override;
37 
38     void contextAbandoned() override;
39 
glContext()40     const GrGLContext& glContext() const { return fGLContext; }
41 
glInterface()42     const GrGLInterface* glInterface() const { return fGLContext.interface(); }
ctxInfo()43     const GrGLContextInfo& ctxInfo() const { return fGLContext; }
glStandard()44     GrGLStandard glStandard() const { return fGLContext.standard(); }
glVersion()45     GrGLVersion glVersion() const { return fGLContext.version(); }
glslGeneration()46     GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); }
glCaps()47     const GrGLCaps& glCaps() const { return *fGLContext.caps(); }
48 
glPathRendering()49     GrGLPathRendering* glPathRendering() {
50         SkASSERT(glCaps().shaderCaps()->pathRenderingSupport());
51         return static_cast<GrGLPathRendering*>(pathRendering());
52     }
53 
54     void discard(GrRenderTarget*) override;
55 
56     // Used by GrGLProgram and GrGLPathTexGenProgramEffects to configure OpenGL
57     // state.
58     void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
59 
60     // GrGpu overrides
61     GrPixelConfig preferredReadPixelsConfig(GrPixelConfig readConfig,
62                                             GrPixelConfig surfaceConfig) const override;
63     GrPixelConfig preferredWritePixelsConfig(GrPixelConfig writeConfig,
64                                              GrPixelConfig surfaceConfig) const override;
65     bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const override;
66     bool readPixelsWillPayForYFlip(GrRenderTarget* renderTarget,
67                                    int left, int top,
68                                    int width, int height,
69                                    GrPixelConfig config,
70                                    size_t rowBytes) const override;
71     bool fullReadPixelsIsFasterThanPartial() const override;
72 
73     bool initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) override;
74 
75     // These functions should be used to bind GL objects. They track the GL state and skip redundant
76     // bindings. Making the equivalent glBind calls directly will confuse the state tracking.
bindVertexArray(GrGLuint id)77     void bindVertexArray(GrGLuint id) {
78         fHWGeometryState.setVertexArrayID(this, id);
79     }
bindIndexBufferAndDefaultVertexArray(GrGLuint id)80     void bindIndexBufferAndDefaultVertexArray(GrGLuint id) {
81         fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, id);
82     }
bindVertexBuffer(GrGLuint id)83     void bindVertexBuffer(GrGLuint id) {
84         fHWGeometryState.setVertexBufferID(this, id);
85     }
86 
87     // These callbacks update state tracking when GL objects are deleted. They are called from
88     // GrGLResource onRelease functions.
notifyVertexArrayDelete(GrGLuint id)89     void notifyVertexArrayDelete(GrGLuint id) {
90         fHWGeometryState.notifyVertexArrayDelete(id);
91     }
notifyVertexBufferDelete(GrGLuint id)92     void notifyVertexBufferDelete(GrGLuint id) {
93         fHWGeometryState.notifyVertexBufferDelete(id);
94     }
notifyIndexBufferDelete(GrGLuint id)95     void notifyIndexBufferDelete(GrGLuint id) {
96         fHWGeometryState.notifyIndexBufferDelete(id);
97     }
98 
99     bool copySurface(GrSurface* dst,
100                      GrSurface* src,
101                      const SkIRect& srcRect,
102                      const SkIPoint& dstPoint) override;
103 
104     bool canCopySurface(const GrSurface* dst,
105                         const GrSurface* src,
106                         const SkIRect& srcRect,
107                         const SkIPoint& dstPoint) override;
108 
109     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override;
110 
111     void buildProgramDesc(GrProgramDesc*,
112                           const GrPrimitiveProcessor&,
113                           const GrPipeline&,
114                           const GrBatchTracker&) const override;
115 
116 private:
117     // GrGpu overrides
118     void onResetContext(uint32_t resetBits) override;
119 
120     GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
121                                const void* srcData, size_t rowBytes) override;
122     GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
123                                          GrGpuResource::LifeCycle lifeCycle,
124                                          const void* srcData) override;
125     GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override;
126     GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override;
127     GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) override;
128     GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) override;
129     bool createStencilAttachmentForRenderTarget(GrRenderTarget* rt, int width, int height) override;
130     bool attachStencilAttachmentToRenderTarget(GrStencilAttachment* sb,
131                                                GrRenderTarget* rt) override;
132 
133     void onClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
134                  bool canIgnoreRect) override;
135 
136     void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override;
137 
138     bool onReadPixels(GrRenderTarget* target,
139                       int left, int top,
140                       int width, int height,
141                       GrPixelConfig,
142                       void* buffer,
143                       size_t rowBytes) override;
144 
145     bool onWriteTexturePixels(GrTexture* texture,
146                               int left, int top, int width, int height,
147                               GrPixelConfig config, const void* buffer,
148                               size_t rowBytes) override;
149 
150     void onResolveRenderTarget(GrRenderTarget* target) override;
151 
152     void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override;
153     void onStencilPath(const GrPath*, const StencilPathState&) override;
154     void onDrawPath(const DrawArgs&, const GrPath*, const GrStencilSettings&) override;
155     void onDrawPaths(const DrawArgs&,
156                      const GrPathRange*,
157                      const void* indices,
158                      GrDrawTarget::PathIndexType,
159                      const float transformValues[],
160                      GrDrawTarget::PathTransformType,
161                      int count,
162                      const GrStencilSettings&) override;
163 
164     void clearStencil(GrRenderTarget*) override;
165 
166     // GrDrawTarget overrides
167     void didAddGpuTraceMarker() override;
168     void didRemoveGpuTraceMarker() override;
169 
170     // binds texture unit in GL
171     void setTextureUnit(int unitIdx);
172 
173     // Flushes state from GrPipeline to GL. Returns false if the state couldn't be set.
174     bool flushGLState(const DrawArgs&);
175 
176     // Sets up vertex attribute pointers and strides. On return indexOffsetInBytes gives the offset
177     // an into the index buffer. It does not account for vertices.startIndex() but rather the start
178     // index is relative to the returned offset.
179     void setupGeometry(const GrPrimitiveProcessor&,
180                        const GrNonInstancedVertices& vertices,
181                        size_t* indexOffsetInBytes);
182 
183     // Subclasses should call this to flush the blend state.
184     void flushBlend(const GrXferProcessor::BlendInfo& blendInfo);
185 
hasExtension(const char * ext)186     bool hasExtension(const char* ext) const { return fGLContext.hasExtension(ext); }
187 
188     static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
189 
190     class ProgramCache : public ::SkNoncopyable {
191     public:
192         ProgramCache(GrGLGpu* gpu);
193         ~ProgramCache();
194 
195         void abandon();
196         GrGLProgram* getProgram(const DrawArgs&);
197 
198     private:
199         enum {
200             // We may actually have kMaxEntries+1 shaders in the GL context because we create a new
201             // shader before evicting from the cache.
202             kMaxEntries = 128,
203             kHashBits = 6,
204         };
205 
206         struct Entry;
207 
208         struct ProgDescLess;
209 
210         // binary search for entry matching desc. returns index into fEntries that matches desc or ~
211         // of the index of where it should be inserted.
212         int search(const GrProgramDesc& desc) const;
213 
214         // sorted array of all the entries
215         Entry*                      fEntries[kMaxEntries];
216         // hash table based on lowest kHashBits bits of the program key. Used to avoid binary
217         // searching fEntries.
218         Entry*                      fHashTable[1 << kHashBits];
219 
220         int                         fCount;
221         unsigned int                fCurrLRUStamp;
222         GrGLGpu*                    fGpu;
223 #ifdef PROGRAM_CACHE_STATS
224         int                         fTotalRequests;
225         int                         fCacheMisses;
226         int                         fHashMisses; // cache hit but hash table missed
227 #endif
228     };
229 
230     void flushDither(bool dither);
231     void flushColorWrite(bool writeColor);
232     void flushDrawFace(GrPipelineBuilder::DrawFace face);
233 
234     // flushes the scissor. see the note on flushBoundTextureAndParams about
235     // flushing the scissor after that function is called.
236     void flushScissor(const GrScissorState&,
237                       const GrGLIRect& rtViewport,
238                       GrSurfaceOrigin rtOrigin);
239 
240     // disables the scissor
241     void disableScissor();
242 
243     void initFSAASupport();
244 
245     // determines valid stencil formats
246     void initStencilFormats();
247 
248     // sets a texture unit to use for texture operations other than binding a texture to a program.
249     // ensures that such operations don't negatively interact with tracking bound textures.
250     void setScratchTextureUnit();
251 
252     // bounds is region that may be modified and therefore has to be resolved.
253     // NULL means whole target. Can be an empty rect.
254     void flushRenderTarget(GrGLRenderTarget*, const SkIRect* bounds);
255 
256     void flushStencil(const GrStencilSettings&);
257     void flushHWAAState(GrRenderTarget* rt, bool useHWAA);
258 
259     bool configToGLFormats(GrPixelConfig config,
260                            bool getSizedInternal,
261                            GrGLenum* internalFormat,
262                            GrGLenum* externalFormat,
263                            GrGLenum* externalType);
264     // helper for onCreateTexture and writeTexturePixels
265     bool uploadTexData(const GrSurfaceDesc& desc,
266                        bool isNewTexture,
267                        int left, int top, int width, int height,
268                        GrPixelConfig dataConfig,
269                        const void* data,
270                        size_t rowBytes);
271 
272     // helper for onCreateCompressedTexture. If width and height are
273     // set to -1, then this function will use desc.fWidth and desc.fHeight
274     // for the size of the data. The isNewTexture flag should be set to true
275     // whenever a new texture needs to be created. Otherwise, we assume that
276     // the texture is already in GPU memory and that it's going to be updated
277     // with new data.
278     bool uploadCompressedTexData(const GrSurfaceDesc& desc,
279                                  const void* data,
280                                  bool isNewTexture = true,
281                                  int left = 0, int top = 0,
282                                  int width = -1, int height = -1);
283 
284     bool createRenderTargetObjects(const GrSurfaceDesc&, GrGpuResource::LifeCycle lifeCycle,
285                                    GrGLuint texID, GrGLRenderTarget::IDDesc*);
286 
287     enum TempFBOTarget {
288         kSrc_TempFBOTarget,
289         kDst_TempFBOTarget
290     };
291 
292     GrGLuint bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
293                               TempFBOTarget tempFBOTarget);
294 
295     void unbindTextureFromFBO(GrGLenum fboTarget);
296 
297     GrGLContext fGLContext;
298 
299     // GL program-related state
300     ProgramCache*               fProgramCache;
301     SkAutoTUnref<GrGLProgram>   fCurrentProgram;
302 
303     ///////////////////////////////////////////////////////////////////////////
304     ///@name Caching of GL State
305     ///@{
306     int                         fHWActiveTextureUnitIdx;
307     GrGLuint                    fHWProgramID;
308 
309     enum TriState {
310         kNo_TriState,
311         kYes_TriState,
312         kUnknown_TriState
313     };
314 
315     GrGLuint                    fTempSrcFBOID;
316     GrGLuint                    fTempDstFBOID;
317 
318     GrGLuint                    fStencilClearFBOID;
319 
320     // last scissor / viewport scissor state seen by the GL.
321     struct {
322         TriState    fEnabled;
323         GrGLIRect   fRect;
invalidate__anon9c78b18a0208324         void invalidate() {
325             fEnabled = kUnknown_TriState;
326             fRect.invalidate();
327         }
328     } fHWScissorSettings;
329 
330     GrGLIRect   fHWViewport;
331 
332     /**
333      * Tracks bound vertex and index buffers and vertex attrib array state.
334      */
335     class HWGeometryState {
336     public:
HWGeometryState()337         HWGeometryState() { fVBOVertexArray = NULL; this->invalidate(); }
338 
~HWGeometryState()339         ~HWGeometryState() { SkDELETE(fVBOVertexArray); }
340 
invalidate()341         void invalidate() {
342             fBoundVertexArrayIDIsValid = false;
343             fBoundVertexBufferIDIsValid = false;
344             fDefaultVertexArrayBoundIndexBufferID = false;
345             fDefaultVertexArrayBoundIndexBufferIDIsValid = false;
346             fDefaultVertexArrayAttribState.invalidate();
347             if (fVBOVertexArray) {
348                 fVBOVertexArray->invalidateCachedState();
349             }
350         }
351 
notifyVertexArrayDelete(GrGLuint id)352         void notifyVertexArrayDelete(GrGLuint id) {
353             if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) {
354                 // Does implicit bind to 0
355                 fBoundVertexArrayID = 0;
356             }
357         }
358 
setVertexArrayID(GrGLGpu * gpu,GrGLuint arrayID)359         void setVertexArrayID(GrGLGpu* gpu, GrGLuint arrayID) {
360             if (!gpu->glCaps().vertexArrayObjectSupport()) {
361                 SkASSERT(0 == arrayID);
362                 return;
363             }
364             if (!fBoundVertexArrayIDIsValid || arrayID != fBoundVertexArrayID) {
365                 GR_GL_CALL(gpu->glInterface(), BindVertexArray(arrayID));
366                 fBoundVertexArrayIDIsValid = true;
367                 fBoundVertexArrayID = arrayID;
368             }
369         }
370 
notifyVertexBufferDelete(GrGLuint id)371         void notifyVertexBufferDelete(GrGLuint id) {
372             if (fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID) {
373                 fBoundVertexBufferID = 0;
374             }
375             if (fVBOVertexArray) {
376                 fVBOVertexArray->notifyVertexBufferDelete(id);
377             }
378             fDefaultVertexArrayAttribState.notifyVertexBufferDelete(id);
379         }
380 
notifyIndexBufferDelete(GrGLuint id)381         void notifyIndexBufferDelete(GrGLuint id) {
382             if (fDefaultVertexArrayBoundIndexBufferIDIsValid &&
383                 id == fDefaultVertexArrayBoundIndexBufferID) {
384                 fDefaultVertexArrayBoundIndexBufferID = 0;
385             }
386             if (fVBOVertexArray) {
387                 fVBOVertexArray->notifyIndexBufferDelete(id);
388             }
389         }
390 
setVertexBufferID(GrGLGpu * gpu,GrGLuint id)391         void setVertexBufferID(GrGLGpu* gpu, GrGLuint id) {
392             if (!fBoundVertexBufferIDIsValid || id != fBoundVertexBufferID) {
393                 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ARRAY_BUFFER, id));
394                 fBoundVertexBufferIDIsValid = true;
395                 fBoundVertexBufferID = id;
396             }
397         }
398 
399         /**
400          * Binds the default vertex array and binds the index buffer. This is used when binding
401          * an index buffer in order to update it.
402          */
setIndexBufferIDOnDefaultVertexArray(GrGLGpu * gpu,GrGLuint id)403         void setIndexBufferIDOnDefaultVertexArray(GrGLGpu* gpu, GrGLuint id) {
404             this->setVertexArrayID(gpu, 0);
405             if (!fDefaultVertexArrayBoundIndexBufferIDIsValid ||
406                 id != fDefaultVertexArrayBoundIndexBufferID) {
407                 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
408                 fDefaultVertexArrayBoundIndexBufferIDIsValid = true;
409                 fDefaultVertexArrayBoundIndexBufferID = id;
410             }
411         }
412 
413         /**
414          * Binds the vertex array object that should be used to render from the vertex buffer.
415          * The vertex array is bound and its attrib array state object is returned. The vertex
416          * buffer is bound. The index buffer (if non-NULL) is bound to the vertex array. The
417          * returned GrGLAttribArrayState should be used to set vertex attribute arrays.
418          */
419         GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGLGpu* gpu,
420                                                         const GrGLVertexBuffer* vbuffer,
421                                                         const GrGLIndexBuffer* ibuffer);
422 
423     private:
424         GrGLuint                fBoundVertexArrayID;
425         GrGLuint                fBoundVertexBufferID;
426         bool                    fBoundVertexArrayIDIsValid;
427         bool                    fBoundVertexBufferIDIsValid;
428 
429         GrGLuint                fDefaultVertexArrayBoundIndexBufferID;
430         bool                    fDefaultVertexArrayBoundIndexBufferIDIsValid;
431         // We return a non-const pointer to this from bindArrayAndBuffersToDraw when vertex array 0
432         // is bound. However, this class is internal to GrGLGpu and this object never leaks out of
433         // GrGLGpu.
434         GrGLAttribArrayState    fDefaultVertexArrayAttribState;
435 
436         // This is used when we're using a core profile and the vertices are in a VBO.
437         GrGLVertexArray*        fVBOVertexArray;
438     } fHWGeometryState;
439 
440     struct {
441         GrBlendEquation fEquation;
442         GrBlendCoeff    fSrcCoeff;
443         GrBlendCoeff    fDstCoeff;
444         GrColor         fConstColor;
445         bool            fConstColorValid;
446         TriState        fEnabled;
447 
invalidate__anon9c78b18a0308448         void invalidate() {
449             fEquation = static_cast<GrBlendEquation>(-1);
450             fSrcCoeff = static_cast<GrBlendCoeff>(-1);
451             fDstCoeff = static_cast<GrBlendCoeff>(-1);
452             fConstColorValid = false;
453             fEnabled = kUnknown_TriState;
454         }
455     } fHWBlendState;
456 
457     TriState fMSAAEnabled;
458 
459     GrStencilSettings           fHWStencilSettings;
460     TriState                    fHWStencilTestEnabled;
461 
462 
463     GrPipelineBuilder::DrawFace fHWDrawFace;
464     TriState                    fHWWriteToColor;
465     TriState                    fHWDitherEnabled;
466     uint32_t                    fHWBoundRenderTargetUniqueID;
467     SkTArray<uint32_t, true>    fHWBoundTextureUniqueIDs;
468 
469     ///@}
470 
471     // we record what stencil format worked last time to hopefully exit early
472     // from our loop that tries stencil formats and calls check fb status.
473     int fLastSuccessfulStencilFmtIdx;
474 
475     typedef GrGpu INHERITED;
476     friend class GrGLPathRendering; // For accessing setTextureUnit.
477 };
478 
479 #endif
480