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 "GrGLTransferBuffer.h"
20#include "GrGLVertexArray.h"
21#include "GrGLVertexBuffer.h"
22#include "GrGpu.h"
23#include "GrPipelineBuilder.h"
24#include "GrXferProcessor.h"
25#include "SkTypes.h"
26
27class GrPipeline;
28class GrNonInstancedVertices;
29class GrSwizzle;
30
31#ifdef SK_DEVELOPER
32#define PROGRAM_CACHE_STATS
33#endif
34
35class GrGLGpu : public GrGpu {
36public:
37    static GrGpu* Create(GrBackendContext backendContext, const GrContextOptions& options,
38                         GrContext* context);
39    ~GrGLGpu() override;
40
41    void contextAbandoned() override;
42
43    const GrGLContext& glContext() const { return *fGLContext; }
44
45    const GrGLInterface* glInterface() const { return fGLContext->interface(); }
46    const GrGLContextInfo& ctxInfo() const { return *fGLContext; }
47    GrGLStandard glStandard() const { return fGLContext->standard(); }
48    GrGLVersion glVersion() const { return fGLContext->version(); }
49    GrGLSLGeneration glslGeneration() const { return fGLContext->glslGeneration(); }
50    const GrGLCaps& glCaps() const { return *fGLContext->caps(); }
51
52    GrGLPathRendering* glPathRendering() {
53        SkASSERT(glCaps().shaderCaps()->pathRenderingSupport());
54        return static_cast<GrGLPathRendering*>(pathRendering());
55    }
56
57    void discard(GrRenderTarget*) override;
58
59    // Used by GrGLProgram to configure OpenGL state.
60    void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
61
62    bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
63                             GrPixelConfig readConfig, DrawPreference*,
64                             ReadPixelTempDrawInfo*) override;
65
66    bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
67                              GrPixelConfig srcConfig, DrawPreference*,
68                              WritePixelTempDrawInfo*) override;
69
70    bool initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const override;
71
72    // These functions should be used to bind GL objects. They track the GL state and skip redundant
73    // bindings. Making the equivalent glBind calls directly will confuse the state tracking.
74    void bindVertexArray(GrGLuint id) {
75        fHWGeometryState.setVertexArrayID(this, id);
76    }
77    void bindIndexBufferAndDefaultVertexArray(GrGLuint id) {
78        fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, id);
79    }
80    void bindVertexBuffer(GrGLuint id) {
81        fHWGeometryState.setVertexBufferID(this, id);
82    }
83
84    // These callbacks update state tracking when GL objects are deleted. They are called from
85    // GrGLResource onRelease functions.
86    void notifyVertexArrayDelete(GrGLuint id) {
87        fHWGeometryState.notifyVertexArrayDelete(id);
88    }
89    void notifyVertexBufferDelete(GrGLuint id) {
90        fHWGeometryState.notifyVertexBufferDelete(id);
91    }
92    void notifyIndexBufferDelete(GrGLuint id) {
93        fHWGeometryState.notifyIndexBufferDelete(id);
94    }
95
96    void buildProgramDesc(GrProgramDesc*,
97                          const GrPrimitiveProcessor&,
98                          const GrPipeline&) const override;
99
100    // id and type (GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER) of buffer to bind
101    void bindBuffer(GrGLuint id, GrGLenum type);
102
103    void releaseBuffer(GrGLuint id, GrGLenum type);
104
105    // sizes are in bytes
106    void* mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, size_t currentSize,
107                    size_t requestedSize);
108
109    void unmapBuffer(GrGLuint id, GrGLenum type, void* mapPtr);
110
111    void bufferData(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, size_t currentSize,
112                    const void* src, size_t srcSizeInBytes);
113
114    const GrGLContext* glContextForTesting() const override {
115        return &this->glContext();
116    }
117
118    void clearStencil(GrRenderTarget*) override;
119
120    void invalidateBoundRenderTarget() {
121        fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
122    }
123
124    GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
125                                                                int width,
126                                                                int height) override;
127
128    GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h,
129                                                    GrPixelConfig config) override;
130    bool isTestingOnlyBackendTexture(GrBackendObject) const override;
131    void deleteTestingOnlyBackendTexture(GrBackendObject, bool abandonTexture) override;
132
133    void resetShaderCacheForTesting() const override;
134
135    void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override;
136
137    void finishDrawTarget() override;
138
139private:
140    GrGLGpu(GrGLContext* ctx, GrContext* context);
141
142    // GrGpu overrides
143    void onResetContext(uint32_t resetBits) override;
144
145    void xferBarrier(GrRenderTarget*, GrXferBarrierType) override;
146
147    GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
148                               const void* srcData, size_t rowBytes) override;
149    GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
150                                         GrGpuResource::LifeCycle lifeCycle,
151                                         const void* srcData) override;
152    GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override;
153    GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override;
154    GrTransferBuffer* onCreateTransferBuffer(size_t size, TransferType type) override;
155    GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) override;
156    GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&,
157                                              GrWrapOwnership) override;
158    GrRenderTarget* onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&,
159                                                       GrWrapOwnership) override;
160    // Given a GrPixelConfig return the index into the stencil format array on GrGLCaps to a
161    // compatible stencil format, or negative if there is no compatible stencil format.
162    int getCompatibleStencilIndex(GrPixelConfig config);
163
164    // If |desc.fTextureStorageAllocator| exists, use that to create the
165    // texture. Otherwise, create the texture directly.
166    // Returns whether the texture is successfully created. On success, the
167    // result is stored in |info|.
168    // The texture is populated with |srcData|, if it exists.
169    // The texture parameters are cached in |initialTexParams|.
170    bool createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info,
171                           bool renderTarget, const void* srcData,
172                           GrGLTexture::TexParams* initialTexParams, size_t rowBytes);
173    bool createTextureExternalAllocatorImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info,
174                                            const void* srcData, size_t rowBytes);
175
176    void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) override;
177
178    void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override;
179
180    bool onMakeCopyForTextureParams(GrTexture*, const GrTextureParams&,
181                                    GrTextureProducer::CopyParams*) const override;
182
183    // Checks whether glReadPixels can be called to get pixel values in readConfig from the
184    // render target.
185    bool readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig);
186
187    // Checks whether glReadPixels can be called to get pixel values in readConfig from a
188    // render target that has renderTargetConfig. This may have to create a temporary
189    // render target and thus is less preferable than the variant that takes a render target.
190    bool readPixelsSupported(GrPixelConfig renderTargetConfig, GrPixelConfig readConfig);
191
192    // Checks whether glReadPixels can be called to get pixel values in readConfig from a
193    // render target that has the same config as surfaceForConfig. Calls one of the the two
194    // variations above, depending on whether the surface is a render target or not.
195    bool readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig);
196
197    bool onReadPixels(GrSurface*,
198                      int left, int top,
199                      int width, int height,
200                      GrPixelConfig,
201                      void* buffer,
202                      size_t rowBytes) override;
203
204    bool onWritePixels(GrSurface*,
205                       int left, int top, int width, int height,
206                       GrPixelConfig config, const void* buffer,
207                       size_t rowBytes) override;
208
209    bool onTransferPixels(GrSurface*,
210                          int left, int top, int width, int height,
211                          GrPixelConfig config, GrTransferBuffer* buffer,
212                          size_t offset, size_t rowBytes) override;
213
214    void onResolveRenderTarget(GrRenderTarget* target) override;
215
216    void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override;
217
218    bool onCopySurface(GrSurface* dst,
219                       GrSurface* src,
220                       const SkIRect& srcRect,
221                       const SkIPoint& dstPoint) override;
222
223    // binds texture unit in GL
224    void setTextureUnit(int unitIdx);
225
226    // Flushes state from GrPipeline to GL. Returns false if the state couldn't be set.
227    bool flushGLState(const DrawArgs&);
228
229    // Sets up vertex attribute pointers and strides. On return indexOffsetInBytes gives the offset
230    // an into the index buffer. It does not account for vertices.startIndex() but rather the start
231    // index is relative to the returned offset.
232    void setupGeometry(const GrPrimitiveProcessor&,
233                       const GrNonInstancedVertices& vertices,
234                       size_t* indexOffsetInBytes);
235
236    void flushBlend(const GrXferProcessor::BlendInfo& blendInfo, const GrSwizzle&);
237
238    bool hasExtension(const char* ext) const { return fGLContext->hasExtension(ext); }
239
240    void copySurfaceAsDraw(GrSurface* dst,
241                           GrSurface* src,
242                           const SkIRect& srcRect,
243                           const SkIPoint& dstPoint);
244    void copySurfaceAsCopyTexSubImage(GrSurface* dst,
245                                      GrSurface* src,
246                                      const SkIRect& srcRect,
247                                      const SkIPoint& dstPoint);
248    bool copySurfaceAsBlitFramebuffer(GrSurface* dst,
249                                      GrSurface* src,
250                                      const SkIRect& srcRect,
251                                      const SkIPoint& dstPoint);
252
253    void stampRectUsingProgram(GrGLuint program, const SkRect& bounds, GrGLint posXformUniform,
254                               GrGLuint arrayBuffer);
255
256    void setupPixelLocalStorage(const DrawArgs& args);
257
258    static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
259
260    class ProgramCache : public ::SkNoncopyable {
261    public:
262        ProgramCache(GrGLGpu* gpu);
263        ~ProgramCache();
264
265        void reset();
266        void abandon();
267        GrGLProgram* refProgram(const DrawArgs&);
268
269    private:
270        enum {
271            // We may actually have kMaxEntries+1 shaders in the GL context because we create a new
272            // shader before evicting from the cache.
273            kMaxEntries = 128,
274            kHashBits = 6,
275        };
276
277        struct Entry;
278
279        struct ProgDescLess;
280
281        // binary search for entry matching desc. returns index into fEntries that matches desc or ~
282        // of the index of where it should be inserted.
283        int search(const GrProgramDesc& desc) const;
284
285        // sorted array of all the entries
286        Entry*                      fEntries[kMaxEntries];
287        // hash table based on lowest kHashBits bits of the program key. Used to avoid binary
288        // searching fEntries.
289        Entry*                      fHashTable[1 << kHashBits];
290
291        int                         fCount;
292        unsigned int                fCurrLRUStamp;
293        GrGLGpu*                    fGpu;
294#ifdef PROGRAM_CACHE_STATS
295        int                         fTotalRequests;
296        int                         fCacheMisses;
297        int                         fHashMisses; // cache hit but hash table missed
298#endif
299    };
300
301    void flushColorWrite(bool writeColor);
302    void flushDrawFace(GrPipelineBuilder::DrawFace face);
303
304    // flushes the scissor. see the note on flushBoundTextureAndParams about
305    // flushing the scissor after that function is called.
306    void flushScissor(const GrScissorState&,
307                      const GrGLIRect& rtViewport,
308                      GrSurfaceOrigin rtOrigin);
309
310    // disables the scissor
311    void disableScissor();
312
313    void initFSAASupport();
314
315    // determines valid stencil formats
316    void initStencilFormats();
317
318    // sets a texture unit to use for texture operations other than binding a texture to a program.
319    // ensures that such operations don't negatively interact with tracking bound textures.
320    void setScratchTextureUnit();
321
322    // bounds is region that may be modified.
323    // nullptr means whole target. Can be an empty rect.
324    void flushRenderTarget(GrGLRenderTarget*, const SkIRect* bounds);
325    // Handles cases where a surface will be updated without a call to flushRenderTarget
326    void didWriteToSurface(GrSurface*, const SkIRect* bounds) const;
327
328    // Need not be called if flushRenderTarget is used.
329    void flushViewport(const GrGLIRect&);
330
331    void flushStencil(const GrStencilSettings&);
332
333    // rt is used only if useHWAA is true.
334    void flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled);
335
336    // helper for onCreateTexture and writeTexturePixels
337    enum UploadType {
338        kNewTexture_UploadType,    // we are creating a new texture
339        kWrite_UploadType,         // we are using TexSubImage2D to copy data to an existing texture
340        kTransfer_UploadType,      // we are using a transfer buffer to copy data
341    };
342    bool uploadTexData(const GrSurfaceDesc& desc,
343                       GrGLenum target,
344                       UploadType uploadType,
345                       int left, int top, int width, int height,
346                       GrPixelConfig dataConfig,
347                       const void* data,
348                       size_t rowBytes);
349
350    // helper for onCreateCompressedTexture. If width and height are
351    // set to -1, then this function will use desc.fWidth and desc.fHeight
352    // for the size of the data. The isNewTexture flag should be set to true
353    // whenever a new texture needs to be created. Otherwise, we assume that
354    // the texture is already in GPU memory and that it's going to be updated
355    // with new data.
356    bool uploadCompressedTexData(const GrSurfaceDesc& desc,
357                                 GrGLenum target,
358                                 const void* data,
359                                 UploadType uploadType = kNewTexture_UploadType,
360                                 int left = 0, int top = 0,
361                                 int width = -1, int height = -1);
362
363    bool createRenderTargetObjects(const GrSurfaceDesc&, GrGpuResource::LifeCycle lifeCycle,
364                                   const GrGLTextureInfo& texInfo, GrGLRenderTarget::IDDesc*);
365
366    enum TempFBOTarget {
367        kSrc_TempFBOTarget,
368        kDst_TempFBOTarget
369    };
370
371    // Binds a surface as a FBO for a copy operation. If the surface already owns an FBO ID then
372    // that ID is bound. If not the surface is temporarily bound to a FBO and that FBO is bound.
373    // This must be paired with a call to unbindSurfaceFBOForCopy().
374    void bindSurfaceFBOForCopy(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
375                              TempFBOTarget tempFBOTarget);
376
377    // Must be called if bindSurfaceFBOForCopy was used to bind a surface for copying.
378    void unbindTextureFBOForCopy(GrGLenum fboTarget, GrSurface* surface);
379
380    SkAutoTUnref<GrGLContext>  fGLContext;
381
382    void createCopyPrograms();
383    void createWireRectProgram();
384    void createUnitRectBuffer();
385
386    void createPLSSetupProgram();
387
388    // GL program-related state
389    ProgramCache*               fProgramCache;
390
391    ///////////////////////////////////////////////////////////////////////////
392    ///@name Caching of GL State
393    ///@{
394    int                         fHWActiveTextureUnitIdx;
395    GrGLuint                    fHWProgramID;
396
397    enum TriState {
398        kNo_TriState,
399        kYes_TriState,
400        kUnknown_TriState
401    };
402
403    GrGLuint                    fTempSrcFBOID;
404    GrGLuint                    fTempDstFBOID;
405
406    GrGLuint                    fStencilClearFBOID;
407
408    // last scissor / viewport scissor state seen by the GL.
409    struct {
410        TriState    fEnabled;
411        GrGLIRect   fRect;
412        void invalidate() {
413            fEnabled = kUnknown_TriState;
414            fRect.invalidate();
415        }
416    } fHWScissorSettings;
417
418    GrGLIRect                   fHWViewport;
419
420    /**
421     * Tracks bound vertex and index buffers and vertex attrib array state.
422     */
423    class HWGeometryState {
424    public:
425        HWGeometryState() { fVBOVertexArray = nullptr; this->invalidate(); }
426
427        ~HWGeometryState() { delete fVBOVertexArray; }
428
429        void invalidate() {
430            fBoundVertexArrayIDIsValid = false;
431            fBoundVertexBufferIDIsValid = false;
432            fDefaultVertexArrayBoundIndexBufferID = false;
433            fDefaultVertexArrayBoundIndexBufferIDIsValid = false;
434            fDefaultVertexArrayAttribState.invalidate();
435            if (fVBOVertexArray) {
436                fVBOVertexArray->invalidateCachedState();
437            }
438        }
439
440        void notifyVertexArrayDelete(GrGLuint id) {
441            if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) {
442                // Does implicit bind to 0
443                fBoundVertexArrayID = 0;
444            }
445        }
446
447        void setVertexArrayID(GrGLGpu* gpu, GrGLuint arrayID) {
448            if (!gpu->glCaps().vertexArrayObjectSupport()) {
449                SkASSERT(0 == arrayID);
450                return;
451            }
452            if (!fBoundVertexArrayIDIsValid || arrayID != fBoundVertexArrayID) {
453                GR_GL_CALL(gpu->glInterface(), BindVertexArray(arrayID));
454                fBoundVertexArrayIDIsValid = true;
455                fBoundVertexArrayID = arrayID;
456            }
457        }
458
459        void notifyVertexBufferDelete(GrGLuint id) {
460            if (fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID) {
461                fBoundVertexBufferID = 0;
462            }
463            if (fVBOVertexArray) {
464                fVBOVertexArray->notifyVertexBufferDelete(id);
465            }
466            fDefaultVertexArrayAttribState.notifyVertexBufferDelete(id);
467        }
468
469        void notifyIndexBufferDelete(GrGLuint id) {
470            if (fDefaultVertexArrayBoundIndexBufferIDIsValid &&
471                id == fDefaultVertexArrayBoundIndexBufferID) {
472                fDefaultVertexArrayBoundIndexBufferID = 0;
473            }
474            if (fVBOVertexArray) {
475                fVBOVertexArray->notifyIndexBufferDelete(id);
476            }
477        }
478
479        void setVertexBufferID(GrGLGpu* gpu, GrGLuint id) {
480            if (!fBoundVertexBufferIDIsValid || id != fBoundVertexBufferID) {
481                GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ARRAY_BUFFER, id));
482                fBoundVertexBufferIDIsValid = true;
483                fBoundVertexBufferID = id;
484            }
485        }
486
487        /**
488         * Binds the default vertex array and binds the index buffer. This is used when binding
489         * an index buffer in order to update it.
490         */
491        void setIndexBufferIDOnDefaultVertexArray(GrGLGpu* gpu, GrGLuint id) {
492            this->setVertexArrayID(gpu, 0);
493            if (!fDefaultVertexArrayBoundIndexBufferIDIsValid ||
494                id != fDefaultVertexArrayBoundIndexBufferID) {
495                GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
496                fDefaultVertexArrayBoundIndexBufferIDIsValid = true;
497                fDefaultVertexArrayBoundIndexBufferID = id;
498            }
499        }
500
501        /**
502         * Binds the vertex array object that should be used to render from the vertex buffer.
503         * The vertex array is bound and its attrib array state object is returned. The vertex
504         * buffer is bound. The index buffer (if non-nullptr) is bound to the vertex array. The
505         * returned GrGLAttribArrayState should be used to set vertex attribute arrays.
506         */
507        GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGLGpu* gpu,
508                                                        const GrGLVertexBuffer* vbuffer,
509                                                        const GrGLIndexBuffer* ibuffer);
510
511        /** Variants of the above that takes GL buffer IDs. Note that 0 does not imply that a
512            buffer won't be bound. The "default buffer" will be bound, which is used for client-side
513            array rendering. */
514        GrGLAttribArrayState* bindArrayAndBufferToDraw(GrGLGpu* gpu, GrGLuint vbufferID);
515        GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGLGpu* gpu,
516                                                        GrGLuint vbufferID,
517                                                        GrGLuint ibufferID);
518
519    private:
520        GrGLAttribArrayState* internalBind(GrGLGpu* gpu, GrGLuint vbufferID, GrGLuint* ibufferID);
521
522        GrGLuint                fBoundVertexArrayID;
523        GrGLuint                fBoundVertexBufferID;
524        bool                    fBoundVertexArrayIDIsValid;
525        bool                    fBoundVertexBufferIDIsValid;
526
527        GrGLuint                fDefaultVertexArrayBoundIndexBufferID;
528        bool                    fDefaultVertexArrayBoundIndexBufferIDIsValid;
529        // We return a non-const pointer to this from bindArrayAndBuffersToDraw when vertex array 0
530        // is bound. However, this class is internal to GrGLGpu and this object never leaks out of
531        // GrGLGpu.
532        GrGLAttribArrayState    fDefaultVertexArrayAttribState;
533
534        // This is used when we're using a core profile and the vertices are in a VBO.
535        GrGLVertexArray*        fVBOVertexArray;
536    } fHWGeometryState;
537
538    struct {
539        GrBlendEquation fEquation;
540        GrBlendCoeff    fSrcCoeff;
541        GrBlendCoeff    fDstCoeff;
542        GrColor         fConstColor;
543        bool            fConstColorValid;
544        TriState        fEnabled;
545
546        void invalidate() {
547            fEquation = static_cast<GrBlendEquation>(-1);
548            fSrcCoeff = static_cast<GrBlendCoeff>(-1);
549            fDstCoeff = static_cast<GrBlendCoeff>(-1);
550            fConstColorValid = false;
551            fEnabled = kUnknown_TriState;
552        }
553    } fHWBlendState;
554
555    TriState fMSAAEnabled;
556
557    GrStencilSettings           fHWStencilSettings;
558    TriState                    fHWStencilTestEnabled;
559
560
561    GrPipelineBuilder::DrawFace fHWDrawFace;
562    TriState                    fHWWriteToColor;
563    uint32_t                    fHWBoundRenderTargetUniqueID;
564    TriState                    fHWSRGBFramebuffer;
565    SkTArray<uint32_t, true>    fHWBoundTextureUniqueIDs;
566
567    // EXT_raster_multisample.
568    TriState                    fHWRasterMultisampleEnabled;
569    int                         fHWNumRasterSamples;
570    ///@}
571
572    /** IDs for copy surface program. */
573    struct {
574        GrGLuint    fProgram;
575        GrGLint     fTextureUniform;
576        GrGLint     fTexCoordXformUniform;
577        GrGLint     fPosXformUniform;
578    }                           fCopyPrograms[3];
579    GrGLuint                    fCopyProgramArrayBuffer;
580
581    struct {
582        GrGLuint fProgram;
583        GrGLint  fColorUniform;
584        GrGLint  fRectUniform;
585    }                           fWireRectProgram;
586    GrGLuint                    fWireRectArrayBuffer;
587
588    static int TextureTargetToCopyProgramIdx(GrGLenum target) {
589        switch (target) {
590            case GR_GL_TEXTURE_2D:
591                return 0;
592            case GR_GL_TEXTURE_EXTERNAL:
593                return 1;
594            case GR_GL_TEXTURE_RECTANGLE:
595                return 2;
596            default:
597                SkFAIL("Unexpected texture target type.");
598                return 0;
599        }
600    }
601
602    struct {
603        GrGLuint    fProgram;
604        GrGLint     fPosXformUniform;
605        GrGLuint    fArrayBuffer;
606    } fPLSSetupProgram;
607
608    bool fHWPLSEnabled;
609    bool fPLSHasBeenUsed;
610
611    typedef GrGpu INHERITED;
612    friend class GrGLPathRendering; // For accessing setTextureUnit.
613};
614
615#endif
616