Home | History | Annotate | Download | only in gl
      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 "GrGLPathRendering.h"
     14 #include "GrGLProgram.h"
     15 #include "GrGLRenderTarget.h"
     16 #include "GrGLStencilAttachment.h"
     17 #include "GrGLTexture.h"
     18 #include "GrGLVertexArray.h"
     19 #include "GrGpu.h"
     20 #include "GrMesh.h"
     21 #include "GrWindowRectsState.h"
     22 #include "GrXferProcessor.h"
     23 #include "SkLRUCache.h"
     24 #include "SkTArray.h"
     25 #include "SkTypes.h"
     26 
     27 class GrGLBuffer;
     28 class GrGLGpuRTCommandBuffer;
     29 class GrGLGpuTextureCommandBuffer;
     30 class GrPipeline;
     31 class GrSwizzle;
     32 
     33 #ifdef SK_DEBUG
     34 #define PROGRAM_CACHE_STATS
     35 #endif
     36 
     37 class GrGLGpu final : public GrGpu, private GrMesh::SendToGpuImpl {
     38 public:
     39     static sk_sp<GrGpu> Make(sk_sp<const GrGLInterface>, const GrContextOptions&, GrContext*);
     40     ~GrGLGpu() override;
     41 
     42     void disconnect(DisconnectType) override;
     43 
     44     const GrGLContext& glContext() const { return *fGLContext; }
     45 
     46     const GrGLInterface* glInterface() const { return fGLContext->interface(); }
     47     const GrGLContextInfo& ctxInfo() const { return *fGLContext; }
     48     GrGLStandard glStandard() const { return fGLContext->standard(); }
     49     GrGLVersion glVersion() const { return fGLContext->version(); }
     50     GrGLSLGeneration glslGeneration() const { return fGLContext->glslGeneration(); }
     51     const GrGLCaps& glCaps() const { return *fGLContext->caps(); }
     52 
     53     GrGLPathRendering* glPathRendering() {
     54         SkASSERT(glCaps().shaderCaps()->pathRenderingSupport());
     55         return static_cast<GrGLPathRendering*>(pathRendering());
     56     }
     57 
     58     // Used by GrGLProgram to configure OpenGL state.
     59     void bindTexture(int unitIdx, GrSamplerState samplerState, GrGLTexture* texture);
     60 
     61     // These functions should be used to bind GL objects. They track the GL state and skip redundant
     62     // bindings. Making the equivalent glBind calls directly will confuse the state tracking.
     63     void bindVertexArray(GrGLuint id) {
     64         fHWVertexArrayState.setVertexArrayID(this, id);
     65     }
     66 
     67     // These callbacks update state tracking when GL objects are deleted. They are called from
     68     // GrGLResource onRelease functions.
     69     void notifyVertexArrayDelete(GrGLuint id) {
     70         fHWVertexArrayState.notifyVertexArrayDelete(id);
     71     }
     72 
     73     // Binds a buffer to the GL target corresponding to 'type', updates internal state tracking, and
     74     // returns the GL target the buffer was bound to.
     75     // When 'type' is kIndex_GrBufferType, this function will also implicitly bind the default VAO.
     76     // If the caller wishes to bind an index buffer to a specific VAO, it can call glBind directly.
     77     GrGLenum bindBuffer(GrGpuBufferType type, const GrBuffer*);
     78 
     79     // The GrGLGpuRTCommandBuffer does not buffer up draws before submitting them to the gpu.
     80     // Thus this is the implementation of the draw call for the corresponding passthrough function
     81     // on GrGLRTGpuCommandBuffer.
     82     void draw(GrRenderTarget*, GrSurfaceOrigin,
     83               const GrPrimitiveProcessor&,
     84               const GrPipeline&,
     85               const GrPipeline::FixedDynamicState*,
     86               const GrPipeline::DynamicStateArrays*,
     87               const GrMesh[],
     88               int meshCount);
     89 
     90     // GrMesh::SendToGpuImpl methods. These issue the actual GL draw calls.
     91     // Marked final as a hint to the compiler to not use virtual dispatch.
     92     void sendMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer, int vertexCount,
     93                        int baseVertex) final;
     94 
     95     void sendIndexedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer, int indexCount,
     96                               int baseIndex, uint16_t minIndexValue, uint16_t maxIndexValue,
     97                               const GrBuffer* vertexBuffer, int baseVertex,
     98                               GrPrimitiveRestart) final;
     99 
    100     void sendInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer, int vertexCount,
    101                                 int baseVertex, const GrBuffer* instanceBuffer, int instanceCount,
    102                                 int baseInstance) final;
    103 
    104     void sendIndexedInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer, int indexCount,
    105                                        int baseIndex, const GrBuffer* vertexBuffer, int baseVertex,
    106                                        const GrBuffer* instanceBuffer, int instanceCount,
    107                                        int baseInstance, GrPrimitiveRestart) final;
    108 
    109     // The GrGLGpuRTCommandBuffer does not buffer up draws before submitting them to the gpu.
    110     // Thus this is the implementation of the clear call for the corresponding passthrough function
    111     // on GrGLGpuRTCommandBuffer.
    112     void clear(const GrFixedClip&, const SkPMColor4f&, GrRenderTarget*, GrSurfaceOrigin);
    113 
    114     // The GrGLGpuRTCommandBuffer does not buffer up draws before submitting them to the gpu.
    115     // Thus this is the implementation of the clearStencil call for the corresponding passthrough
    116     // function on GrGLGpuRTCommandBuffer.
    117     void clearStencilClip(const GrFixedClip&, bool insideStencilMask,
    118                           GrRenderTarget*, GrSurfaceOrigin);
    119 
    120     // FIXME (michaelludwig): Can this go away and just use clearStencilClip() + marking the
    121     // stencil buffer as not dirty?
    122     void clearStencil(GrRenderTarget*, int clearValue);
    123 
    124     GrGpuRTCommandBuffer* getCommandBuffer(
    125             GrRenderTarget*, GrSurfaceOrigin, const SkRect&,
    126             const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
    127             const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) override;
    128 
    129     GrGpuTextureCommandBuffer* getCommandBuffer(GrTexture*, GrSurfaceOrigin) override;
    130 
    131     void invalidateBoundRenderTarget() {
    132         fHWBoundRenderTargetUniqueID.makeInvalid();
    133     }
    134 
    135     GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
    136                                                                 int width,
    137                                                                 int height) override;
    138 #if GR_TEST_UTILS
    139     GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h,
    140                                                      GrColorType colorType, bool isRenderTarget,
    141                                                      GrMipMapped mipMapped,
    142                                                      size_t rowBytes = 0) override;
    143     bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
    144     void deleteTestingOnlyBackendTexture(const GrBackendTexture&) override;
    145 
    146     GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
    147 
    148     void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
    149 
    150     const GrGLContext* glContextForTesting() const override { return &this->glContext(); }
    151 
    152     void resetShaderCacheForTesting() const override { fProgramCache->abandon(); }
    153 
    154     void testingOnly_flushGpuAndSync() override;
    155 #endif
    156 
    157     void submit(GrGpuCommandBuffer* buffer) override;
    158 
    159     GrFence SK_WARN_UNUSED_RESULT insertFence() override;
    160     bool waitFence(GrFence, uint64_t timeout) override;
    161     void deleteFence(GrFence) const override;
    162 
    163     sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override;
    164     sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
    165                                             GrResourceProvider::SemaphoreWrapType wrapType,
    166                                             GrWrapOwnership ownership) override;
    167     void insertSemaphore(sk_sp<GrSemaphore> semaphore) override;
    168     void waitSemaphore(sk_sp<GrSemaphore> semaphore) override;
    169 
    170     sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override;
    171 
    172     void deleteSync(GrGLsync) const;
    173 
    174     void insertEventMarker(const char*);
    175 
    176     void bindFramebuffer(GrGLenum fboTarget, GrGLuint fboid);
    177     void deleteFramebuffer(GrGLuint fboid);
    178 
    179 private:
    180     GrGLGpu(std::unique_ptr<GrGLContext>, GrContext*);
    181 
    182     // GrGpu overrides
    183     void onResetContext(uint32_t resetBits) override;
    184 
    185     void onResetTextureBindings() override;
    186 
    187     void querySampleLocations(
    188             GrRenderTarget*, const GrStencilSettings&, SkTArray<SkPoint>*) override;
    189 
    190     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override;
    191 
    192     sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
    193                                      const GrMipLevel texels[], int mipLevelCount) override;
    194 
    195     sk_sp<GrGpuBuffer> onCreateBuffer(size_t size, GrGpuBufferType intendedType, GrAccessPattern,
    196                                       const void* data) override;
    197 
    198     sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
    199                                           GrIOType) override;
    200     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt,
    201                                                     GrWrapOwnership, GrWrapCacheable) override;
    202     sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override;
    203     sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
    204                                                              int sampleCnt) override;
    205 
    206     // Given a GrPixelConfig return the index into the stencil format array on GrGLCaps to a
    207     // compatible stencil format, or negative if there is no compatible stencil format.
    208     int getCompatibleStencilIndex(GrPixelConfig config);
    209 
    210     void onFBOChanged();
    211 
    212     // Returns whether the texture is successfully created. On success, the
    213     // result is stored in |info|.
    214     // The texture is populated with |texels|, if it exists.
    215     // The texture parameters are cached in |initialTexParams|.
    216     bool createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info, bool renderTarget,
    217                            GrGLTexture::SamplerParams* initialTexParams, const GrMipLevel texels[],
    218                            int mipLevelCount, GrMipMapsStatus* mipMapsStatus);
    219 
    220     // Checks whether glReadPixels can be called to get pixel values in readConfig from the
    221     // render target.
    222     bool readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig);
    223 
    224     // Checks whether glReadPixels can be called to get pixel values in readConfig from a
    225     // render target that has renderTargetConfig. This may have to create a temporary
    226     // render target and thus is less preferable than the variant that takes a render target.
    227     bool readPixelsSupported(GrPixelConfig renderTargetConfig, GrPixelConfig readConfig);
    228 
    229     // Checks whether glReadPixels can be called to get pixel values in readConfig from a
    230     // render target that has the same config as surfaceForConfig. Calls one of the the two
    231     // variations above, depending on whether the surface is a render target or not.
    232     bool readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig);
    233 
    234     bool onReadPixels(GrSurface*, int left, int top, int width, int height, GrColorType,
    235                       void* buffer, size_t rowBytes) override;
    236 
    237     bool onWritePixels(GrSurface*, int left, int top, int width, int height, GrColorType,
    238                        const GrMipLevel texels[], int mipLevelCount) override;
    239 
    240     bool onTransferPixels(GrTexture*, int left, int top, int width, int height, GrColorType,
    241                           GrGpuBuffer* transferBuffer, size_t offset, size_t rowBytes) override;
    242 
    243     // Before calling any variation of TexImage, TexSubImage, etc..., call this to ensure that the
    244     // PIXEL_UNPACK_BUFFER is unbound.
    245     void unbindCpuToGpuXferBuffer();
    246 
    247     void onResolveRenderTarget(GrRenderTarget* target) override;
    248 
    249     bool onRegenerateMipMapLevels(GrTexture*) override;
    250 
    251     bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
    252                        GrSurface* src, GrSurfaceOrigin srcOrigin,
    253                        const SkIRect& srcRect, const SkIPoint& dstPoint,
    254                        bool canDiscardOutsideDstRect) override;
    255 
    256     // binds texture unit in GL
    257     void setTextureUnit(int unitIdx);
    258 
    259     /**
    260      * primitiveProcessorTextures must contain GrPrimitiveProcessor::numTextureSamplers() *
    261      * numPrimitiveProcessorTextureSets entries.
    262      */
    263     void resolveAndGenerateMipMapsForProcessorTextures(
    264             const GrPrimitiveProcessor&, const GrPipeline&,
    265             const GrTextureProxy* const primitiveProcessorTextures[],
    266             int numPrimitiveProcessorTextureSets);
    267 
    268     // Flushes state from GrPipeline to GL. Returns false if the state couldn't be set.
    269     // willDrawPoints must be true if point primitives will be rendered after setting the GL state.
    270     // If DynamicStateArrays is not null then dynamicStateArraysLength is the number of dynamic
    271     // state entries in each array.
    272     bool flushGLState(GrRenderTarget*, GrSurfaceOrigin, const GrPrimitiveProcessor&,
    273                       const GrPipeline&, const GrPipeline::FixedDynamicState*,
    274                       const GrPipeline::DynamicStateArrays*, int dynamicStateArraysLength,
    275                       bool willDrawPoints);
    276 
    277     void flushProgram(sk_sp<GrGLProgram>);
    278 
    279     // Version for programs that aren't GrGLProgram.
    280     void flushProgram(GrGLuint);
    281 
    282     // Sets up vertex/instance attribute pointers and strides.
    283     void setupGeometry(const GrBuffer* indexBuffer,
    284                        const GrBuffer* vertexBuffer,
    285                        int baseVertex,
    286                        const GrBuffer* instanceBuffer,
    287                        int baseInstance,
    288                        GrPrimitiveRestart);
    289 
    290     void flushBlend(const GrXferProcessor::BlendInfo& blendInfo, const GrSwizzle&);
    291 
    292     void onFinishFlush(GrSurfaceProxy*, SkSurface::BackendSurfaceAccess access,
    293                        GrFlushFlags flags, bool insertedSemaphores,
    294                        GrGpuFinishedProc finishedProc,
    295                        GrGpuFinishedContext finishedContext) override;
    296 
    297     bool copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
    298                            GrSurface* src, GrSurfaceOrigin srcOrigin,
    299                            const SkIRect& srcRect, const SkIPoint& dstPoint);
    300     void copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
    301                                       GrSurface* src, GrSurfaceOrigin srcOrigin,
    302                                       const SkIRect& srcRect, const SkIPoint& dstPoint);
    303     bool copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurfaceOrigin dstOrigin,
    304                                       GrSurface* src, GrSurfaceOrigin srcOrigin,
    305                                       const SkIRect& srcRect, const SkIPoint& dstPoint);
    306 
    307     static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
    308 
    309     class ProgramCache : public ::SkNoncopyable {
    310     public:
    311         ProgramCache(GrGLGpu* gpu);
    312         ~ProgramCache();
    313 
    314         void abandon();
    315         GrGLProgram* refProgram(GrGLGpu*, GrRenderTarget*, GrSurfaceOrigin,
    316                                 const GrPrimitiveProcessor&,
    317                                 const GrTextureProxy* const primProcProxies[],
    318                                 const GrPipeline&, bool hasPointSize);
    319 
    320     private:
    321         // We may actually have kMaxEntries+1 shaders in the GL context because we create a new
    322         // shader before evicting from the cache.
    323         static const int kMaxEntries = 128;
    324 
    325         struct Entry;
    326 
    327         // binary search for entry matching desc. returns index into fEntries that matches desc or ~
    328         // of the index of where it should be inserted.
    329         int search(const GrProgramDesc& desc) const;
    330 
    331         struct DescHash {
    332             uint32_t operator()(const GrProgramDesc& desc) const {
    333                 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
    334             }
    335         };
    336 
    337         SkLRUCache<GrProgramDesc, std::unique_ptr<Entry>, DescHash> fMap;
    338 
    339         GrGLGpu*                    fGpu;
    340 #ifdef PROGRAM_CACHE_STATS
    341         int                         fTotalRequests;
    342         int                         fCacheMisses;
    343         int                         fHashMisses; // cache hit but hash table missed
    344 #endif
    345     };
    346 
    347     void flushColorWrite(bool writeColor);
    348     void flushClearColor(GrGLfloat r, GrGLfloat g, GrGLfloat b, GrGLfloat a);
    349 
    350     // flushes the scissor. see the note on flushBoundTextureAndParams about
    351     // flushing the scissor after that function is called.
    352     void flushScissor(const GrScissorState&,
    353                       const GrGLIRect& rtViewport,
    354                       GrSurfaceOrigin rtOrigin);
    355 
    356     // disables the scissor
    357     void disableScissor();
    358 
    359     void flushWindowRectangles(const GrWindowRectsState&, const GrGLRenderTarget*, GrSurfaceOrigin);
    360     void disableWindowRectangles();
    361 
    362     int numTextureUnits() const { return this->caps()->shaderCaps()->maxFragmentSamplers(); }
    363 
    364     // Binds a texture to a target on the "scratch" texture unit to use for texture operations
    365     // other than usual draw flow (i.e. a GrGLProgram derived from a GrPipeline used to draw
    366     // GrMesh). It ensures that such operations don't negatively interact with draws.
    367     // The active texture unit and the binding for 'target' will change.
    368     void bindTextureToScratchUnit(GrGLenum target, GrGLint textureID);
    369 
    370     // The passed bounds contains the render target's color values that will subsequently be
    371     // written.
    372     void flushRenderTarget(GrGLRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds);
    373     // This version has an implicit bounds of the entire render target.
    374     void flushRenderTarget(GrGLRenderTarget*);
    375     // This version can be used when the render target's colors will not be written.
    376     void flushRenderTargetNoColorWrites(GrGLRenderTarget*);
    377 
    378     // Need not be called if flushRenderTarget is used.
    379     void flushViewport(const GrGLIRect&);
    380 
    381     void flushStencil(const GrStencilSettings&);
    382     void disableStencil();
    383 
    384     // rt is used only if useHWAA is true.
    385     void flushHWAAState(GrRenderTarget* rt, bool useHWAA);
    386 
    387     void flushFramebufferSRGB(bool enable);
    388 
    389     // helper for onCreateTexture and writeTexturePixels
    390     enum UploadType {
    391         kNewTexture_UploadType,   // we are creating a new texture
    392         kWrite_UploadType,        // we are using TexSubImage2D to copy data to an existing texture
    393     };
    394     bool uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight, GrGLenum target,
    395                        UploadType uploadType, int left, int top, int width, int height,
    396                        GrPixelConfig dataConfig, const GrMipLevel texels[], int mipLevelCount,
    397                        GrMipMapsStatus* mipMapsStatus = nullptr);
    398 
    399     // helper for onCreateCompressedTexture. Compressed textures are read-only so we
    400     // only use this to populate a new texture.
    401     bool uploadCompressedTexData(GrPixelConfig texConfig, int texWidth, int texHeight,
    402                                  GrGLenum target, GrPixelConfig dataConfig,
    403                                  const GrMipLevel texels[], int mipLevelCount,
    404                                  GrMipMapsStatus* mipMapsStatus = nullptr);
    405 
    406     bool createRenderTargetObjects(const GrSurfaceDesc&, const GrGLTextureInfo& texInfo,
    407                                    GrGLRenderTarget::IDDesc*);
    408 
    409     enum TempFBOTarget {
    410         kSrc_TempFBOTarget,
    411         kDst_TempFBOTarget
    412     };
    413 
    414     // Binds a surface as a FBO for copying, reading, or clearing. If the surface already owns an
    415     // FBO ID then that ID is bound. If not the surface is temporarily bound to a FBO and that FBO
    416     // is bound. This must be paired with a call to unbindSurfaceFBOForPixelOps().
    417     void bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
    418                                    TempFBOTarget tempFBOTarget);
    419 
    420     // Must be called if bindSurfaceFBOForPixelOps was used to bind a surface for copying.
    421     void unbindTextureFBOForPixelOps(GrGLenum fboTarget, GrSurface* surface);
    422 
    423 #ifdef SK_ENABLE_DUMP_GPU
    424     void onDumpJSON(SkJSONWriter*) const override;
    425 #endif
    426 
    427     bool createCopyProgram(GrTexture* srcTexture);
    428     bool createMipmapProgram(int progIdx);
    429 
    430     std::unique_ptr<GrGLContext> fGLContext;
    431 
    432     // GL program-related state
    433     ProgramCache*               fProgramCache;
    434 
    435     ///////////////////////////////////////////////////////////////////////////
    436     ///@name Caching of GL State
    437     ///@{
    438     int                         fHWActiveTextureUnitIdx;
    439 
    440     GrGLuint                    fHWProgramID;
    441     sk_sp<GrGLProgram>          fHWProgram;
    442 
    443     enum TriState {
    444         kNo_TriState,
    445         kYes_TriState,
    446         kUnknown_TriState
    447     };
    448 
    449     GrGLuint                    fTempSrcFBOID;
    450     GrGLuint                    fTempDstFBOID;
    451 
    452     GrGLuint                    fStencilClearFBOID;
    453 
    454     // last scissor / viewport scissor state seen by the GL.
    455     struct {
    456         TriState    fEnabled;
    457         GrGLIRect   fRect;
    458         void invalidate() {
    459             fEnabled = kUnknown_TriState;
    460             fRect.invalidate();
    461         }
    462     } fHWScissorSettings;
    463 
    464     class {
    465     public:
    466         bool valid() const { return kInvalidSurfaceOrigin != fRTOrigin; }
    467         void invalidate() { fRTOrigin = kInvalidSurfaceOrigin; }
    468         bool knownDisabled() const { return this->valid() && !fWindowState.enabled(); }
    469         void setDisabled() {
    470             fRTOrigin = kTopLeft_GrSurfaceOrigin;
    471             fWindowState.setDisabled();
    472         }
    473 
    474         void set(GrSurfaceOrigin rtOrigin, const GrGLIRect& viewport,
    475                  const GrWindowRectsState& windowState) {
    476             fRTOrigin = rtOrigin;
    477             fViewport = viewport;
    478             fWindowState = windowState;
    479         }
    480 
    481         bool knownEqualTo(GrSurfaceOrigin rtOrigin, const GrGLIRect& viewport,
    482                           const GrWindowRectsState& windowState) const {
    483             if (!this->valid()) {
    484                 return false;
    485             }
    486             if (fWindowState.numWindows() && (fRTOrigin != rtOrigin || fViewport != viewport)) {
    487                 return false;
    488             }
    489             return fWindowState == windowState;
    490         }
    491 
    492     private:
    493         enum { kInvalidSurfaceOrigin = -1 };
    494 
    495         int                  fRTOrigin;
    496         GrGLIRect            fViewport;
    497         GrWindowRectsState   fWindowState;
    498     } fHWWindowRectsState;
    499 
    500     GrGLIRect                   fHWViewport;
    501 
    502     /**
    503      * Tracks vertex attrib array state.
    504      */
    505     class HWVertexArrayState {
    506     public:
    507         HWVertexArrayState() : fCoreProfileVertexArray(nullptr) { this->invalidate(); }
    508 
    509         ~HWVertexArrayState() { delete fCoreProfileVertexArray; }
    510 
    511         void invalidate() {
    512             fBoundVertexArrayIDIsValid = false;
    513             fDefaultVertexArrayAttribState.invalidate();
    514             if (fCoreProfileVertexArray) {
    515                 fCoreProfileVertexArray->invalidateCachedState();
    516             }
    517         }
    518 
    519         void notifyVertexArrayDelete(GrGLuint id) {
    520             if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) {
    521                 // Does implicit bind to 0
    522                 fBoundVertexArrayID = 0;
    523             }
    524         }
    525 
    526         void setVertexArrayID(GrGLGpu* gpu, GrGLuint arrayID) {
    527             if (!gpu->glCaps().vertexArrayObjectSupport()) {
    528                 SkASSERT(0 == arrayID);
    529                 return;
    530             }
    531             if (!fBoundVertexArrayIDIsValid || arrayID != fBoundVertexArrayID) {
    532                 GR_GL_CALL(gpu->glInterface(), BindVertexArray(arrayID));
    533                 fBoundVertexArrayIDIsValid = true;
    534                 fBoundVertexArrayID = arrayID;
    535             }
    536         }
    537 
    538         /**
    539          * Binds the vertex array that should be used for internal draws, and returns its attrib
    540          * state. This binds the default VAO (ID=zero) unless we are on a core profile, in which
    541          * case we use a dummy array instead.
    542          *
    543          * If an index buffer is privided, it will be bound to the vertex array. Otherwise the
    544          * index buffer binding will be left unchanged.
    545          *
    546          * The returned GrGLAttribArrayState should be used to set vertex attribute arrays.
    547          */
    548         GrGLAttribArrayState* bindInternalVertexArray(GrGLGpu*, const GrBuffer* ibuff = nullptr);
    549 
    550     private:
    551         GrGLuint             fBoundVertexArrayID;
    552         bool                 fBoundVertexArrayIDIsValid;
    553 
    554         // We return a non-const pointer to this from bindArrayAndBuffersToDraw when vertex array 0
    555         // is bound. However, this class is internal to GrGLGpu and this object never leaks out of
    556         // GrGLGpu.
    557         GrGLAttribArrayState fDefaultVertexArrayAttribState;
    558 
    559         // This is used when we're using a core profile.
    560         GrGLVertexArray*     fCoreProfileVertexArray;
    561     }                                       fHWVertexArrayState;
    562 
    563     struct {
    564         GrGLenum                fGLTarget;
    565         GrGpuResource::UniqueID fBoundBufferUniqueID;
    566         bool                    fBufferZeroKnownBound;
    567 
    568         void invalidate() {
    569             fBoundBufferUniqueID.makeInvalid();
    570             fBufferZeroKnownBound = false;
    571         }
    572     }                                       fHWBufferState[kGrGpuBufferTypeCount];
    573 
    574     auto* hwBufferState(GrGpuBufferType type) {
    575         unsigned typeAsUInt = static_cast<unsigned>(type);
    576         SkASSERT(typeAsUInt < SK_ARRAY_COUNT(fHWBufferState));
    577         return &fHWBufferState[typeAsUInt];
    578     }
    579 
    580     struct {
    581         GrBlendEquation fEquation;
    582         GrBlendCoeff    fSrcCoeff;
    583         GrBlendCoeff    fDstCoeff;
    584         SkPMColor4f     fConstColor;
    585         bool            fConstColorValid;
    586         TriState        fEnabled;
    587 
    588         void invalidate() {
    589             fEquation = kIllegal_GrBlendEquation;
    590             fSrcCoeff = kIllegal_GrBlendCoeff;
    591             fDstCoeff = kIllegal_GrBlendCoeff;
    592             fConstColorValid = false;
    593             fEnabled = kUnknown_TriState;
    594         }
    595     }                                       fHWBlendState;
    596 
    597     TriState                                fMSAAEnabled;
    598 
    599     GrStencilSettings                       fHWStencilSettings;
    600     TriState                                fHWStencilTestEnabled;
    601 
    602 
    603     TriState                                fHWWriteToColor;
    604     GrGpuResource::UniqueID                 fHWBoundRenderTargetUniqueID;
    605     TriState                                fHWSRGBFramebuffer;
    606 
    607     class TextureUnitBindings {
    608     public:
    609         TextureUnitBindings() = default;
    610         TextureUnitBindings(const TextureUnitBindings&) = delete;
    611         TextureUnitBindings& operator=(const TextureUnitBindings&) = delete;
    612 
    613         GrGpuResource::UniqueID boundID(GrGLenum target) const;
    614         bool hasBeenModified(GrGLenum target) const;
    615         void setBoundID(GrGLenum target, GrGpuResource::UniqueID);
    616         void invalidateForScratchUse(GrGLenum target);
    617         void invalidateAllTargets(bool markUnmodified);
    618 
    619     private:
    620         struct TargetBinding {
    621             GrGpuResource::UniqueID fBoundResourceID;
    622             bool fHasBeenModified = false;
    623         };
    624         TargetBinding fTargetBindings[3];
    625     };
    626     SkAutoTArray<TextureUnitBindings> fHWTextureUnitBindings;
    627 
    628     GrGLfloat fHWClearColor[4];
    629 
    630     GrGLuint fBoundDrawFramebuffer = 0;
    631 
    632     /** IDs for copy surface program. (3 sampler types) */
    633     struct {
    634         GrGLuint    fProgram = 0;
    635         GrGLint     fTextureUniform = 0;
    636         GrGLint     fTexCoordXformUniform = 0;
    637         GrGLint     fPosXformUniform = 0;
    638     }                                       fCopyPrograms[3];
    639     sk_sp<GrGLBuffer>                       fCopyProgramArrayBuffer;
    640 
    641     /** IDs for texture mipmap program. (4 filter configurations) */
    642     struct {
    643         GrGLuint    fProgram = 0;
    644         GrGLint     fTextureUniform = 0;
    645         GrGLint     fTexCoordXformUniform = 0;
    646     }                                       fMipmapPrograms[4];
    647     sk_sp<GrGLBuffer>                       fMipmapProgramArrayBuffer;
    648 
    649     static int TextureToCopyProgramIdx(GrTexture* texture);
    650 
    651     static int TextureSizeToMipmapProgramIdx(int width, int height) {
    652         const bool wide = (width > 1) && SkToBool(width & 0x1);
    653         const bool tall = (height > 1) && SkToBool(height & 0x1);
    654         return (wide ? 0x2 : 0x0) | (tall ? 0x1 : 0x0);
    655     }
    656 
    657     GrPrimitiveType fLastPrimitiveType;
    658 
    659     class SamplerObjectCache;
    660     std::unique_ptr<SamplerObjectCache> fSamplerObjectCache;
    661 
    662     std::unique_ptr<GrGLGpuRTCommandBuffer>      fCachedRTCommandBuffer;
    663     std::unique_ptr<GrGLGpuTextureCommandBuffer> fCachedTexCommandBuffer;
    664 
    665     friend class GrGLPathRendering; // For accessing setTextureUnit.
    666 
    667     typedef GrGpu INHERITED;
    668 };
    669 
    670 #endif
    671