blob: 1785eae1430cd221d8fb3921def3caeda4eb040b [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00006 */
7
jvanverth39edf762014-12-22 11:44:19 -08008#ifndef GrGLGpu_DEFINED
9#define GrGLGpu_DEFINED
reed@google.comac10a2d2010-12-22 21:39:39 +000010
robertphillips@google.com6177e692013-02-28 20:16:25 +000011#include "GrGLContext.h"
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +000012#include "GrGLIRect.h"
kkinnunenccdaa042014-08-20 01:36:23 -070013#include "GrGLPathRendering.h"
bsalomon@google.com5739d2c2012-05-31 15:07:19 +000014#include "GrGLProgram.h"
bsalomon37dd3312014-11-03 08:47:23 -080015#include "GrGLRenderTarget.h"
egdaniel8dc7c3a2015-04-16 11:22:42 -070016#include "GrGLStencilAttachment.h"
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +000017#include "GrGLTexture.h"
bsalomon@google.com6918d482013-03-07 19:09:11 +000018#include "GrGLVertexArray.h"
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +000019#include "GrGpu.h"
Chris Dalton114a3c02017-05-26 15:17:19 -060020#include "GrMesh.h"
Brian Salomonbf7b6202016-11-11 16:08:03 -050021#include "GrTexturePriv.h"
csmartdaltonbf4a8f92016-09-06 10:01:06 -070022#include "GrWindowRectsState.h"
egdaniel080e6732014-12-22 07:35:52 -080023#include "GrXferProcessor.h"
Ethan Nicholas1b9924f2016-12-15 15:28:42 -050024#include "SkLRUCache.h"
cblume55f2d2d2016-02-26 13:20:48 -080025#include "SkTArray.h"
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +000026#include "SkTypes.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000027
cdalton397536c2016-03-25 12:15:03 -070028class GrGLBuffer;
egdaniel8dd688b2015-01-22 10:16:09 -080029class GrPipeline;
bsalomon7f9b2e42016-01-12 13:29:26 -080030class GrSwizzle;
egdaniel8dd688b2015-01-22 10:16:09 -080031
csmartdaltona7f29642016-07-07 08:49:11 -070032namespace gr_instanced { class GLInstancedRendering; }
33
djsollenefe46d22016-04-29 06:41:35 -070034#ifdef SK_DEBUG
jvanverth@google.com94878772013-03-12 16:00:54 +000035#define PROGRAM_CACHE_STATS
36#endif
37
Chris Dalton114a3c02017-05-26 15:17:19 -060038class GrGLGpu final : public GrGpu, private GrMesh::SendToGpuImpl {
reed@google.comac10a2d2010-12-22 21:39:39 +000039public:
bsalomon682c2692015-05-22 14:01:46 -070040 static GrGpu* Create(GrBackendContext backendContext, const GrContextOptions& options,
41 GrContext* context);
mtklein36352bf2015-03-25 18:17:31 -070042 ~GrGLGpu() override;
reed@google.comac10a2d2010-12-22 21:39:39 +000043
bsalomon6e2aad42016-04-01 11:54:31 -070044 void disconnect(DisconnectType) override;
bsalomonc8dc1f72014-08-21 13:02:13 -070045
bsalomon424cc262015-05-22 10:37:30 -070046 const GrGLContext& glContext() const { return *fGLContext; }
commit-bot@chromium.orgc9424b82013-10-30 20:03:16 +000047
bsalomon424cc262015-05-22 10:37:30 -070048 const GrGLInterface* glInterface() const { return fGLContext->interface(); }
49 const GrGLContextInfo& ctxInfo() const { return *fGLContext; }
50 GrGLStandard glStandard() const { return fGLContext->standard(); }
51 GrGLVersion glVersion() const { return fGLContext->version(); }
52 GrGLSLGeneration glslGeneration() const { return fGLContext->glslGeneration(); }
53 const GrGLCaps& glCaps() const { return *fGLContext->caps(); }
bsalomon@google.com0b77d682011-08-19 13:28:54 +000054
kkinnunenccdaa042014-08-20 01:36:23 -070055 GrGLPathRendering* glPathRendering() {
jvanverthe9c0fc62015-04-29 11:18:05 -070056 SkASSERT(glCaps().shaderCaps()->pathRenderingSupport());
kkinnunenccdaa042014-08-20 01:36:23 -070057 return static_cast<GrGLPathRendering*>(pathRendering());
cdaltonc7103a12014-08-11 14:05:05 -070058 }
59
kkinnunencfe62e32015-07-01 02:58:50 -070060 // Used by GrGLProgram to configure OpenGL state.
Brian Salomon514baff2016-11-17 15:17:07 -050061 void bindTexture(int unitIdx, const GrSamplerParams& params, bool allowSRGBInputs,
brianosmana6359362016-03-21 06:55:37 -070062 GrGLTexture* texture);
kkinnunenccdaa042014-08-20 01:36:23 -070063
csmartdalton1897cfd2016-06-03 08:50:54 -070064 void bindTexelBuffer(int unitIdx, GrPixelConfig, GrGLBuffer*);
cdalton74b8d322016-04-11 14:47:28 -070065
Brian Salomonf9f45122016-11-29 11:59:17 -050066 void bindImageStorage(int unitIdx, GrIOType, GrGLTexture *);
67
Brian Salomon514baff2016-11-17 15:17:07 -050068 void generateMipmaps(const GrSamplerParams& params, bool allowSRGBInputs, GrGLTexture* texture);
brianosman33f6b3f2016-06-02 05:49:21 -070069
bsalomonf0674512015-07-28 13:26:15 -070070 bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
71 GrPixelConfig readConfig, DrawPreference*,
72 ReadPixelTempDrawInfo*) override;
bsalomon39826022015-07-23 08:07:21 -070073
bsalomonf0674512015-07-28 13:26:15 -070074 bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
cblumeed828002016-02-16 13:00:01 -080075 GrPixelConfig srcConfig, DrawPreference*,
bsalomonf0674512015-07-28 13:26:15 -070076 WritePixelTempDrawInfo*) override;
bsalomon@google.com75f9f252012-01-31 13:35:56 +000077
bsalomon@google.com6918d482013-03-07 19:09:11 +000078 // These functions should be used to bind GL objects. They track the GL state and skip redundant
skia.committer@gmail.com754a3eb2013-03-08 07:01:25 +000079 // bindings. Making the equivalent glBind calls directly will confuse the state tracking.
bsalomon@google.com6918d482013-03-07 19:09:11 +000080 void bindVertexArray(GrGLuint id) {
cdaltone2e71c22016-04-07 18:13:29 -070081 fHWVertexArrayState.setVertexArrayID(this, id);
bsalomon@google.com6918d482013-03-07 19:09:11 +000082 }
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) {
cdaltone2e71c22016-04-07 18:13:29 -070087 fHWVertexArrayState.notifyVertexArrayDelete(id);
bsalomon@google.com6918d482013-03-07 19:09:11 +000088 }
bsalomon@google.com880b8fc2013-02-19 20:17:28 +000089
cdaltone2e71c22016-04-07 18:13:29 -070090 // Binds a buffer to the GL target corresponding to 'type', updates internal state tracking, and
91 // returns the GL target the buffer was bound to.
92 // When 'type' is kIndex_GrBufferType, this function will also implicitly bind the default VAO.
93 // If the caller wishes to bind an index buffer to a specific VAO, it can call glBind directly.
csmartdalton485a1202016-07-13 10:16:32 -070094 GrGLenum bindBuffer(GrBufferType type, const GrBuffer*);
joshualitt93316b92015-10-23 09:08:08 -070095
cdalton74b8d322016-04-11 14:47:28 -070096 // Called by GrGLBuffer after its buffer object has been destroyed.
97 void notifyBufferReleased(const GrGLBuffer*);
98
egdaniel9cb63402016-06-23 08:37:05 -070099 // The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu.
100 // Thus this is the implementation of the draw call for the corresponding passthrough function
101 // on GrGLGpuCommandBuffer.
102 void draw(const GrPipeline&,
103 const GrPrimitiveProcessor&,
104 const GrMesh*,
105 int meshCount);
106
Chris Dalton114a3c02017-05-26 15:17:19 -0600107
108 // GrMesh::SendToGpuImpl methods. These issue the actual GL draw calls.
109 // Marked final as a hint to the compiler to not use virtual dispatch.
110 void sendMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
111 const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) final;
112
113 void sendIndexedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
114 const GrBuffer* indexBuffer, int indexCount, int baseIndex,
115 uint16_t minIndexValue, uint16_t maxIndexValue,
116 const GrBuffer* vertexBuffer, int baseVertex) final;
117
Chris Dalton1d616352017-05-31 12:51:23 -0600118 void sendInstancedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
119 const GrBuffer* vertexBuffer, int vertexCount, int baseVertex,
120 const GrBuffer* instanceBuffer, int instanceCount,
121 int baseInstance) final;
122
123 void sendIndexedInstancedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
124 const GrBuffer* indexBuffer, int indexCount, int baseIndex,
125 const GrBuffer* vertexBuffer, int baseVertex,
126 const GrBuffer* instanceBuffer, int instanceCount,
127 int baseInstance) final;
128
egdaniel9cb63402016-06-23 08:37:05 -0700129 // The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu.
130 // Thus this is the implementation of the clear call for the corresponding passthrough function
131 // on GrGLGpuCommandBuffer.
csmartdalton29df7602016-08-31 11:55:52 -0700132 void clear(const GrFixedClip&, GrColor, GrRenderTarget*);
egdaniel9cb63402016-06-23 08:37:05 -0700133
134 // The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu.
135 // Thus this is the implementation of the clearStencil call for the corresponding passthrough
136 // function on GrGLGpuCommandBuffer.
csmartdalton29df7602016-08-31 11:55:52 -0700137 void clearStencilClip(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*);
egdaniel9cb63402016-06-23 08:37:05 -0700138
reedf9ad5582015-06-25 21:29:25 -0700139 const GrGLContext* glContextForTesting() const override {
140 return &this->glContext();
bsalomon993a4212015-05-29 11:37:25 -0700141 }
142
egdanielec00d942015-09-14 12:56:10 -0700143 void clearStencil(GrRenderTarget*) override;
144
egdaniel9cb63402016-06-23 08:37:05 -0700145 GrGpuCommandBuffer* createCommandBuffer(
egdaniel9cb63402016-06-23 08:37:05 -0700146 const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
147 const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) override;
egdaniel066df7c2016-06-08 14:02:27 -0700148
egdanielec00d942015-09-14 12:56:10 -0700149 void invalidateBoundRenderTarget() {
Robert Phillips294870f2016-11-11 12:38:40 -0500150 fHWBoundRenderTargetUniqueID.makeInvalid();
egdanielec00d942015-09-14 12:56:10 -0700151 }
152
153 GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
154 int width,
155 int height) override;
156
jvanverth88957922015-07-14 11:02:52 -0700157 GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h,
egdaniel0a3a7f72016-06-24 09:22:31 -0700158 GrPixelConfig config,
159 bool isRenderTarget = false) override;
bsalomon67d76202015-11-11 12:40:42 -0800160 bool isTestingOnlyBackendTexture(GrBackendObject) const override;
bsalomone63ffef2016-02-05 07:17:34 -0800161 void deleteTestingOnlyBackendTexture(GrBackendObject, bool abandonTexture) override;
jvanverth672bb7f2015-07-13 07:19:57 -0700162
joshualitt8fd844f2015-12-02 13:36:47 -0800163 void resetShaderCacheForTesting() const override;
164
Greg Daniel6be35232017-03-01 17:01:09 -0500165 GrFence SK_WARN_UNUSED_RESULT insertFence() override;
166 bool waitFence(GrFence, uint64_t timeout) override;
jvanverth84741b32016-09-30 08:39:02 -0700167 void deleteFence(GrFence) const override;
168
Greg Daniel6be35232017-03-01 17:01:09 -0500169 sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore() override;
Brian Osmandc87c952017-04-28 13:57:38 -0400170 void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override;
Greg Daniel6be35232017-03-01 17:01:09 -0500171 void waitSemaphore(sk_sp<GrSemaphore> semaphore) override;
172
Brian Osman13dddce2017-05-09 13:19:50 -0400173 sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override;
174
Greg Daniel6be35232017-03-01 17:01:09 -0500175 void deleteSync(GrGLsync) const;
176
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000177private:
bsalomon424cc262015-05-22 10:37:30 -0700178 GrGLGpu(GrGLContext* ctx, GrContext* context);
179
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000180 // GrGpu overrides
mtklein36352bf2015-03-25 18:17:31 -0700181 void onResetContext(uint32_t resetBits) override;
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000182
bsalomoncb02b382015-08-12 11:14:50 -0700183 void xferBarrier(GrRenderTarget*, GrXferBarrierType) override;
184
Robert Phillips67d52cf2017-06-05 13:38:13 -0400185 sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
186 const SkTArray<GrMipLevel>& texels) override;
cblume55f2d2d2016-02-26 13:20:48 -0800187
cdalton1bf3e712016-04-19 10:00:02 -0700188 GrBuffer* onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern,
189 const void* data) override;
Greg Daniel7ef28f32017-04-20 16:41:55 +0000190
191 sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&,
192 GrSurfaceOrigin,
193 GrBackendTextureFlags,
194 int sampleCnt,
195 GrWrapOwnership) override;
Greg Danielbcf612b2017-05-01 13:50:58 +0000196 sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&,
197 GrSurfaceOrigin origin) override;
Greg Daniel7ef28f32017-04-20 16:41:55 +0000198 sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
199 GrSurfaceOrigin,
200 int sampleCnt) override;
csmartdaltone0d36292016-07-29 08:14:20 -0700201
Robert Phillipse3302df2017-04-24 07:31:02 -0400202 std::unique_ptr<gr_instanced::OpAllocator> onCreateInstancedRenderingAllocator() override;
csmartdaltone0d36292016-07-29 08:14:20 -0700203 gr_instanced::InstancedRendering* onCreateInstancedRendering() override;
204
egdanielff1d5472015-09-10 08:37:20 -0700205 // Given a GrPixelConfig return the index into the stencil format array on GrGLCaps to a
bsalomon62a627b2015-12-17 09:50:47 -0800206 // compatible stencil format, or negative if there is no compatible stencil format.
egdanielff1d5472015-09-10 08:37:20 -0700207 int getCompatibleStencilIndex(GrPixelConfig config);
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000208
bsalomon7e68ab72016-04-13 14:29:25 -0700209
erikchen9a1ed5d2016-02-10 16:32:34 -0800210 // Returns whether the texture is successfully created. On success, the
211 // result is stored in |info|.
cblume55f2d2d2016-02-26 13:20:48 -0800212 // The texture is populated with |texels|, if it exists.
erikchen9a1ed5d2016-02-10 16:32:34 -0800213 // The texture parameters are cached in |initialTexParams|.
214 bool createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info,
cblume55f2d2d2016-02-26 13:20:48 -0800215 bool renderTarget, GrGLTexture::TexParams* initialTexParams,
216 const SkTArray<GrMipLevel>& texels);
erikchen9a1ed5d2016-02-10 16:32:34 -0800217
Robert Phillips3798c862017-03-27 11:08:16 -0400218 bool onIsACopyNeededForTextureParams(GrTextureProxy*, const GrSamplerParams&,
Robert Phillips81444fb2017-03-21 09:14:35 -0400219 GrTextureProducer::CopyParams*,
220 SkScalar scaleAdjust[2]) const override;
bsalomone179a912016-01-20 06:18:10 -0800221
bsalomon1aa20292016-01-22 08:16:09 -0800222 // Checks whether glReadPixels can be called to get pixel values in readConfig from the
223 // render target.
224 bool readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig);
225
226 // Checks whether glReadPixels can be called to get pixel values in readConfig from a
227 // render target that has renderTargetConfig. This may have to create a temporary
228 // render target and thus is less preferable than the variant that takes a render target.
229 bool readPixelsSupported(GrPixelConfig renderTargetConfig, GrPixelConfig readConfig);
230
231 // Checks whether glReadPixels can be called to get pixel values in readConfig from a
232 // render target that has the same config as surfaceForConfig. Calls one of the the two
233 // variations above, depending on whether the surface is a render target or not.
234 bool readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig);
235
bsalomon6cb3cbe2015-07-30 07:34:27 -0700236 bool onReadPixels(GrSurface*,
bsalomond95263c2014-12-16 13:05:12 -0800237 int left, int top,
238 int width, int height,
239 GrPixelConfig,
240 void* buffer,
mtklein36352bf2015-03-25 18:17:31 -0700241 size_t rowBytes) override;
bsalomond95263c2014-12-16 13:05:12 -0800242
bsalomon6cb3cbe2015-07-30 07:34:27 -0700243 bool onWritePixels(GrSurface*,
244 int left, int top, int width, int height,
cblume55f2d2d2016-02-26 13:20:48 -0800245 GrPixelConfig config,
246 const SkTArray<GrMipLevel>& texels) override;
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000247
jvanverthc3d706f2016-04-20 10:33:27 -0700248 bool onTransferPixels(GrSurface*,
jvanverth17aa0472016-01-05 10:41:27 -0800249 int left, int top, int width, int height,
cdalton397536c2016-03-25 12:15:03 -0700250 GrPixelConfig config, GrBuffer* transferBuffer,
jvanverth17aa0472016-01-05 10:41:27 -0800251 size_t offset, size_t rowBytes) override;
252
mtklein36352bf2015-03-25 18:17:31 -0700253 void onResolveRenderTarget(GrRenderTarget* target) override;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000254
joshualitt1cbdcde2015-08-21 11:53:29 -0700255 bool onCopySurface(GrSurface* dst,
256 GrSurface* src,
257 const SkIRect& srcRect,
258 const SkIPoint& dstPoint) override;
259
csmartdaltonc25c5d72016-11-01 07:03:59 -0700260 void onQueryMultisampleSpecs(GrRenderTarget*, const GrStencilSettings&,
261 int* effectiveSampleCnt, SamplePattern*) override;
cdalton28f45b92016-03-07 13:58:26 -0800262
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000263 // binds texture unit in GL
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000264 void setTextureUnit(int unitIdx);
reed@google.comac10a2d2010-12-22 21:39:39 +0000265
cdalton74b8d322016-04-11 14:47:28 -0700266 void setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]);
267
egdaniel8dd688b2015-01-22 10:16:09 -0800268 // Flushes state from GrPipeline to GL. Returns false if the state couldn't be set.
bsalomon2eda5b32016-09-21 10:53:24 -0700269 // willDrawPoints must be true if point primitives will be rendered after setting the GL state.
270 bool flushGLState(const GrPipeline&, const GrPrimitiveProcessor&, bool willDrawPoints);
bsalomond95263c2014-12-16 13:05:12 -0800271
Chris Dalton114a3c02017-05-26 15:17:19 -0600272 // Sets up vertex/instance attribute pointers and strides.
joshualitt873ad0e2015-01-20 09:08:51 -0800273 void setupGeometry(const GrPrimitiveProcessor&,
Chris Daltonff926502017-05-03 14:36:54 -0400274 const GrBuffer* indexBuffer,
275 const GrBuffer* vertexBuffer,
Chris Dalton1d616352017-05-31 12:51:23 -0600276 int baseVertex,
277 const GrBuffer* instanceBuffer,
278 int baseInstance);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000279
bsalomon7f9b2e42016-01-12 13:29:26 -0800280 void flushBlend(const GrXferProcessor::BlendInfo& blendInfo, const GrSwizzle&);
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000281
bsalomon424cc262015-05-22 10:37:30 -0700282 bool hasExtension(const char* ext) const { return fGLContext->hasExtension(ext); }
bsalomon@google.com96399942012-02-13 14:39:16 +0000283
cdaltone2e71c22016-04-07 18:13:29 -0700284 bool copySurfaceAsDraw(GrSurface* dst,
bsalomon6df86402015-06-01 10:41:49 -0700285 GrSurface* src,
286 const SkIRect& srcRect,
287 const SkIPoint& dstPoint);
288 void copySurfaceAsCopyTexSubImage(GrSurface* dst,
289 GrSurface* src,
290 const SkIRect& srcRect,
291 const SkIPoint& dstPoint);
292 bool copySurfaceAsBlitFramebuffer(GrSurface* dst,
293 GrSurface* src,
294 const SkIRect& srcRect,
295 const SkIPoint& dstPoint);
brianosman33f6b3f2016-06-02 05:49:21 -0700296 bool generateMipmap(GrGLTexture* texture, bool gammaCorrect);
Mike Klein31550db2017-06-06 23:29:53 +0000297 void clearStencilClipAsDraw(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*);
bsalomon6df86402015-06-01 10:41:49 -0700298
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000299 static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
bsalomon@google.com080773c2011-03-15 19:09:25 +0000300
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000301 class ProgramCache : public ::SkNoncopyable {
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000302 public:
bsalomon861e1032014-12-16 07:33:49 -0800303 ProgramCache(GrGLGpu* gpu);
jvanverth@google.com94878772013-03-12 16:00:54 +0000304 ~ProgramCache();
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000305
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000306 void abandon();
bsalomon2eda5b32016-09-21 10:53:24 -0700307 GrGLProgram* refProgram(const GrGLGpu*, const GrPipeline&, const GrPrimitiveProcessor&,
308 bool hasPointSize);
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000309
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000310 private:
Ethan Nicholas1b9924f2016-12-15 15:28:42 -0500311 // We may actually have kMaxEntries+1 shaders in the GL context because we create a new
312 // shader before evicting from the cache.
313 static const int kMaxEntries = 128;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000314
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000315 struct Entry;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000316
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000317 // binary search for entry matching desc. returns index into fEntries that matches desc or ~
318 // of the index of where it should be inserted.
joshualitt79f8fae2014-10-28 17:59:26 -0700319 int search(const GrProgramDesc& desc) const;
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000320
Ethan Nicholas1b9924f2016-12-15 15:28:42 -0500321 struct DescHash {
322 uint32_t operator()(const GrProgramDesc& desc) const {
323 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
324 }
325 };
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000326
Ethan Nicholas1b9924f2016-12-15 15:28:42 -0500327 SkLRUCache<GrProgramDesc, std::unique_ptr<Entry>, DescHash> fMap;
328
bsalomon861e1032014-12-16 07:33:49 -0800329 GrGLGpu* fGpu;
jvanverth@google.com94878772013-03-12 16:00:54 +0000330#ifdef PROGRAM_CACHE_STATS
331 int fTotalRequests;
332 int fCacheMisses;
bsalomon@google.com2db3ded2013-05-22 14:34:04 +0000333 int fHashMisses; // cache hit but hash table missed
jvanverth@google.com94878772013-03-12 16:00:54 +0000334#endif
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000335 };
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000336
egdaniel080e6732014-12-22 07:35:52 -0800337 void flushColorWrite(bool writeColor);
bsalomon@google.comc96cb3a2012-06-04 19:31:00 +0000338
bsalomon@google.coma3201942012-06-21 19:58:20 +0000339 // flushes the scissor. see the note on flushBoundTextureAndParams about
340 // flushing the scissor after that function is called.
bsalomon3e791242014-12-17 13:43:13 -0800341 void flushScissor(const GrScissorState&,
joshualitt77b13072014-10-27 14:51:01 -0700342 const GrGLIRect& rtViewport,
343 GrSurfaceOrigin rtOrigin);
344
345 // disables the scissor
346 void disableScissor();
bsalomon@google.coma3201942012-06-21 19:58:20 +0000347
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700348 void flushWindowRectangles(const GrWindowRectsState&, const GrGLRenderTarget*);
csmartdalton28341fa2016-08-17 10:00:21 -0700349 void disableWindowRectangles();
350
commit-bot@chromium.orga15f7e52013-06-05 23:29:25 +0000351 // sets a texture unit to use for texture operations other than binding a texture to a program.
352 // ensures that such operations don't negatively interact with tracking bound textures.
353 void setScratchTextureUnit();
reed@google.comac10a2d2010-12-22 21:39:39 +0000354
bsalomon083617b2016-02-12 12:10:14 -0800355 // bounds is region that may be modified.
halcanary96fcdcc2015-08-27 07:41:13 -0700356 // nullptr means whole target. Can be an empty rect.
brianosman64d094d2016-03-25 06:01:59 -0700357 void flushRenderTarget(GrGLRenderTarget*, const SkIRect* bounds, bool disableSRGB = false);
bsalomon083617b2016-02-12 12:10:14 -0800358
359 // Need not be called if flushRenderTarget is used.
360 void flushViewport(const GrGLIRect&);
bsalomonb0bd4f62014-09-03 07:19:50 -0700361
bsalomon3e791242014-12-17 13:43:13 -0800362 void flushStencil(const GrStencilSettings&);
csmartdaltonc7d85332016-10-26 10:13:46 -0700363 void disableStencil();
bsalomon083617b2016-02-12 12:10:14 -0800364
365 // rt is used only if useHWAA is true.
cdaltonaf8bc7d2016-02-05 09:35:20 -0800366 void flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled);
bsalomon@google.com0650e812011-04-08 18:07:53 +0000367
ethannicholas28ef4452016-03-25 09:26:03 -0700368 void flushMinSampleShading(float minSampleShading);
369
brianosman33f6b3f2016-06-02 05:49:21 -0700370 void flushFramebufferSRGB(bool enable);
371
bsalomon@google.com6f379512011-11-16 20:36:03 +0000372 // helper for onCreateTexture and writeTexturePixels
jvanverth17aa0472016-01-05 10:41:27 -0800373 enum UploadType {
374 kNewTexture_UploadType, // we are creating a new texture
375 kWrite_UploadType, // we are using TexSubImage2D to copy data to an existing texture
376 kTransfer_UploadType, // we are using a transfer buffer to copy data
377 };
Brian Salomond1eaf492017-05-18 10:02:08 -0400378 bool uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight,
379 GrSurfaceOrigin texOrigin, GrGLenum target, UploadType uploadType, int left,
380 int top, int width, int height, GrPixelConfig dataConfig,
cblume55f2d2d2016-02-26 13:20:48 -0800381 const SkTArray<GrMipLevel>& texels);
bsalomon@google.com0650e812011-04-08 18:07:53 +0000382
kkinnunen2e6055b2016-04-22 01:48:29 -0700383 bool createRenderTargetObjects(const GrSurfaceDesc&, const GrGLTextureInfo& texInfo,
384 GrGLRenderTarget::IDDesc*);
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000385
egdanield803f272015-03-18 13:01:52 -0700386 enum TempFBOTarget {
387 kSrc_TempFBOTarget,
388 kDst_TempFBOTarget
389 };
egdaniel0f5f9672015-02-03 11:10:51 -0800390
Brian Salomond17b4a62017-05-23 16:53:47 -0400391 // Binds a surface as a FBO for copying, reading, or clearing. If the surface already owns an
392 // FBO ID then that ID is bound. If not the surface is temporarily bound to a FBO and that FBO
393 // is bound. This must be paired with a call to unbindSurfaceFBOForPixelOps().
Brian Salomon71d9d842016-11-03 13:42:00 -0400394 void bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
395 TempFBOTarget tempFBOTarget);
egdaniel0f5f9672015-02-03 11:10:51 -0800396
Brian Salomon71d9d842016-11-03 13:42:00 -0400397 // Must be called if bindSurfaceFBOForPixelOps was used to bind a surface for copying.
398 void unbindTextureFBOForPixelOps(GrGLenum fboTarget, GrSurface* surface);
robertphillips754f4e92014-09-18 13:52:08 -0700399
Hal Canary144caf52016-11-07 17:57:18 -0500400 sk_sp<GrGLContext> fGLContext;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000401
Brian Salomonbf7b6202016-11-11 16:08:03 -0500402 bool createCopyProgram(GrTexture* srcTexture);
brianosman33f6b3f2016-06-02 05:49:21 -0700403 bool createMipmapProgram(int progIdx);
Mike Klein31550db2017-06-06 23:29:53 +0000404 bool createStencilClipClearProgram();
ethannicholas22793252016-01-30 09:59:10 -0800405
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000406 // GL program-related state
407 ProgramCache* fProgramCache;
bsalomon@google.com49209392012-06-05 15:13:46 +0000408
409 ///////////////////////////////////////////////////////////////////////////
410 ///@name Caching of GL State
411 ///@{
412 int fHWActiveTextureUnitIdx;
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000413 GrGLuint fHWProgramID;
bsalomon@google.com91207482013-02-12 21:45:24 +0000414
bsalomon@google.com49209392012-06-05 15:13:46 +0000415 enum TriState {
416 kNo_TriState,
417 kYes_TriState,
418 kUnknown_TriState
419 };
420
egdanield803f272015-03-18 13:01:52 -0700421 GrGLuint fTempSrcFBOID;
422 GrGLuint fTempDstFBOID;
423
424 GrGLuint fStencilClearFBOID;
bsalomondd3143b2015-02-23 09:27:45 -0800425
bsalomon@google.coma3201942012-06-21 19:58:20 +0000426 // last scissor / viewport scissor state seen by the GL.
427 struct {
428 TriState fEnabled;
429 GrGLIRect fRect;
430 void invalidate() {
431 fEnabled = kUnknown_TriState;
432 fRect.invalidate();
433 }
434 } fHWScissorSettings;
435
csmartdalton28341fa2016-08-17 10:00:21 -0700436 class {
437 public:
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700438 bool valid() const { return kInvalidSurfaceOrigin != fRTOrigin; }
439 void invalidate() { fRTOrigin = kInvalidSurfaceOrigin; }
440 bool knownDisabled() const { return this->valid() && !fWindowState.enabled(); }
mtklein8b4a2022016-09-26 08:44:47 -0700441 void setDisabled() {
442 fRTOrigin = kDefault_GrSurfaceOrigin;
443 fWindowState.setDisabled();
444 }
csmartdalton28341fa2016-08-17 10:00:21 -0700445
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700446 void set(GrSurfaceOrigin rtOrigin, const GrGLIRect& viewport,
447 const GrWindowRectsState& windowState) {
448 fRTOrigin = rtOrigin;
449 fViewport = viewport;
450 fWindowState = windowState;
csmartdalton28341fa2016-08-17 10:00:21 -0700451 }
csmartdalton28341fa2016-08-17 10:00:21 -0700452
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700453 bool knownEqualTo(GrSurfaceOrigin rtOrigin, const GrGLIRect& viewport,
454 const GrWindowRectsState& windowState) const {
csmartdalton28341fa2016-08-17 10:00:21 -0700455 if (!this->valid()) {
456 return false;
457 }
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700458 if (fWindowState.numWindows() && (fRTOrigin != rtOrigin || fViewport != viewport)) {
csmartdalton28341fa2016-08-17 10:00:21 -0700459 return false;
460 }
Brian Salomon9a767722017-03-13 17:57:28 -0400461 return fWindowState == windowState;
csmartdalton28341fa2016-08-17 10:00:21 -0700462 }
463
464 private:
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700465 enum { kInvalidSurfaceOrigin = -1 };
csmartdalton28341fa2016-08-17 10:00:21 -0700466
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700467 int fRTOrigin;
csmartdalton28341fa2016-08-17 10:00:21 -0700468 GrGLIRect fViewport;
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700469 GrWindowRectsState fWindowState;
470 } fHWWindowRectsState;
csmartdalton28341fa2016-08-17 10:00:21 -0700471
bsalomon424cc262015-05-22 10:37:30 -0700472 GrGLIRect fHWViewport;
bsalomon@google.coma3201942012-06-21 19:58:20 +0000473
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000474 /**
cdaltone2e71c22016-04-07 18:13:29 -0700475 * Tracks vertex attrib array state.
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000476 */
cdaltone2e71c22016-04-07 18:13:29 -0700477 class HWVertexArrayState {
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000478 public:
cdaltone2e71c22016-04-07 18:13:29 -0700479 HWVertexArrayState() : fCoreProfileVertexArray(nullptr) { this->invalidate(); }
skia.committer@gmail.com754a3eb2013-03-08 07:01:25 +0000480
cdaltone2e71c22016-04-07 18:13:29 -0700481 ~HWVertexArrayState() { delete fCoreProfileVertexArray; }
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000482
bsalomon@google.com6918d482013-03-07 19:09:11 +0000483 void invalidate() {
484 fBoundVertexArrayIDIsValid = false;
bsalomon@google.com6918d482013-03-07 19:09:11 +0000485 fDefaultVertexArrayAttribState.invalidate();
cdaltone2e71c22016-04-07 18:13:29 -0700486 if (fCoreProfileVertexArray) {
487 fCoreProfileVertexArray->invalidateCachedState();
commit-bot@chromium.orgce6da4d2013-09-09 14:55:37 +0000488 }
bsalomon@google.com6918d482013-03-07 19:09:11 +0000489 }
490
491 void notifyVertexArrayDelete(GrGLuint id) {
492 if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) {
493 // Does implicit bind to 0
494 fBoundVertexArrayID = 0;
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000495 }
496 }
497
bsalomon861e1032014-12-16 07:33:49 -0800498 void setVertexArrayID(GrGLGpu* gpu, GrGLuint arrayID) {
bsalomon@google.com6918d482013-03-07 19:09:11 +0000499 if (!gpu->glCaps().vertexArrayObjectSupport()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000500 SkASSERT(0 == arrayID);
bsalomon@google.com6918d482013-03-07 19:09:11 +0000501 return;
502 }
503 if (!fBoundVertexArrayIDIsValid || arrayID != fBoundVertexArrayID) {
504 GR_GL_CALL(gpu->glInterface(), BindVertexArray(arrayID));
505 fBoundVertexArrayIDIsValid = true;
506 fBoundVertexArrayID = arrayID;
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000507 }
508 }
509
bsalomon@google.com6918d482013-03-07 19:09:11 +0000510 /**
cdaltone2e71c22016-04-07 18:13:29 -0700511 * Binds the vertex array that should be used for internal draws, and returns its attrib
512 * state. This binds the default VAO (ID=zero) unless we are on a core profile, in which
513 * case we use a dummy array instead.
514 *
515 * If an index buffer is privided, it will be bound to the vertex array. Otherwise the
516 * index buffer binding will be left unchanged.
517 *
518 * The returned GrGLAttribArrayState should be used to set vertex attribute arrays.
bsalomon@google.com6918d482013-03-07 19:09:11 +0000519 */
csmartdalton485a1202016-07-13 10:16:32 -0700520 GrGLAttribArrayState* bindInternalVertexArray(GrGLGpu*, const GrBuffer* ibuff = nullptr);
bsalomon6df86402015-06-01 10:41:49 -0700521
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000522 private:
Robert Phillips294870f2016-11-11 12:38:40 -0500523 GrGLuint fBoundVertexArrayID;
524 bool fBoundVertexArrayIDIsValid;
mtklein044d3c12016-04-06 18:24:34 -0700525
bsalomon@google.com6918d482013-03-07 19:09:11 +0000526 // We return a non-const pointer to this from bindArrayAndBuffersToDraw when vertex array 0
jvanverth39edf762014-12-22 11:44:19 -0800527 // is bound. However, this class is internal to GrGLGpu and this object never leaks out of
528 // GrGLGpu.
Robert Phillips294870f2016-11-11 12:38:40 -0500529 GrGLAttribArrayState fDefaultVertexArrayAttribState;
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000530
cdaltone2e71c22016-04-07 18:13:29 -0700531 // This is used when we're using a core profile.
Robert Phillips294870f2016-11-11 12:38:40 -0500532 GrGLVertexArray* fCoreProfileVertexArray;
533 } fHWVertexArrayState;
bsalomon@google.com5782d712011-01-21 21:03:59 +0000534
cdaltone2e71c22016-04-07 18:13:29 -0700535 struct {
Robert Phillips294870f2016-11-11 12:38:40 -0500536 GrGLenum fGLTarget;
537 GrGpuResource::UniqueID fBoundBufferUniqueID;
538 bool fBufferZeroKnownBound;
cdaltone2e71c22016-04-07 18:13:29 -0700539
540 void invalidate() {
Robert Phillips294870f2016-11-11 12:38:40 -0500541 fBoundBufferUniqueID.makeInvalid();
cdaltone2e71c22016-04-07 18:13:29 -0700542 fBufferZeroKnownBound = false;
543 }
Robert Phillips294870f2016-11-11 12:38:40 -0500544 } fHWBufferState[kGrBufferTypeCount];
cdaltonc1613102016-03-16 07:48:20 -0700545
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +0000546 struct {
cdalton8917d622015-05-06 13:40:21 -0700547 GrBlendEquation fEquation;
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +0000548 GrBlendCoeff fSrcCoeff;
549 GrBlendCoeff fDstCoeff;
550 GrColor fConstColor;
551 bool fConstColorValid;
552 TriState fEnabled;
553
554 void invalidate() {
bsalomonf7cc8772015-05-11 11:21:14 -0700555 fEquation = static_cast<GrBlendEquation>(-1);
556 fSrcCoeff = static_cast<GrBlendCoeff>(-1);
557 fDstCoeff = static_cast<GrBlendCoeff>(-1);
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +0000558 fConstColorValid = false;
559 fEnabled = kUnknown_TriState;
560 }
Robert Phillips294870f2016-11-11 12:38:40 -0500561 } fHWBlendState;
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +0000562
bsalomon54c6fe82015-12-16 11:51:22 -0800563 TriState fMSAAEnabled;
564
Robert Phillips294870f2016-11-11 12:38:40 -0500565 GrStencilSettings fHWStencilSettings;
566 TriState fHWStencilTestEnabled;
bsalomon54c6fe82015-12-16 11:51:22 -0800567
568
Robert Phillips294870f2016-11-11 12:38:40 -0500569 TriState fHWWriteToColor;
570 GrGpuResource::UniqueID fHWBoundRenderTargetUniqueID;
571 TriState fHWSRGBFramebuffer;
572 SkTArray<GrGpuResource::UniqueID, true> fHWBoundTextureUniqueIDs;
cdaltonaf8bc7d2016-02-05 09:35:20 -0800573
Brian Salomonf9f45122016-11-29 11:59:17 -0500574 struct Image {
575 GrGpuResource::UniqueID fTextureUniqueID;
576 GrIOType fIOType;
577 };
578 SkTArray<Image, true> fHWBoundImageStorages;
579
cdalton74b8d322016-04-11 14:47:28 -0700580 struct BufferTexture {
581 BufferTexture() : fTextureID(0), fKnownBound(false),
582 fAttachedBufferUniqueID(SK_InvalidUniqueID),
583 fSwizzle(GrSwizzle::RGBA()) {}
584
Robert Phillips294870f2016-11-11 12:38:40 -0500585 GrGLuint fTextureID;
586 bool fKnownBound;
587 GrPixelConfig fTexelConfig;
588 GrGpuResource::UniqueID fAttachedBufferUniqueID;
589 GrSwizzle fSwizzle;
cdalton74b8d322016-04-11 14:47:28 -0700590 };
591
Robert Phillips294870f2016-11-11 12:38:40 -0500592 SkTArray<BufferTexture, true> fHWBufferTextures;
593 int fHWMaxUsedBufferTextureUnit;
cdalton74b8d322016-04-11 14:47:28 -0700594
cdaltonaf8bc7d2016-02-05 09:35:20 -0800595 // EXT_raster_multisample.
Robert Phillips294870f2016-11-11 12:38:40 -0500596 TriState fHWRasterMultisampleEnabled;
597 int fHWNumRasterSamples;
bsalomon54c6fe82015-12-16 11:51:22 -0800598 ///@}
599
Brian Salomonbf7b6202016-11-11 16:08:03 -0500600 /** IDs for copy surface program. (4 sampler types) */
bsalomon6df86402015-06-01 10:41:49 -0700601 struct {
602 GrGLuint fProgram;
603 GrGLint fTextureUniform;
604 GrGLint fTexCoordXformUniform;
605 GrGLint fPosXformUniform;
Brian Salomonbf7b6202016-11-11 16:08:03 -0500606 } fCopyPrograms[4];
Robert Phillips294870f2016-11-11 12:38:40 -0500607 sk_sp<GrGLBuffer> fCopyProgramArrayBuffer;
bsalomon7ea33f52015-11-22 14:51:00 -0800608
brianosman33f6b3f2016-06-02 05:49:21 -0700609 /** IDs for texture mipmap program. (4 filter configurations) */
610 struct {
611 GrGLuint fProgram;
612 GrGLint fTextureUniform;
613 GrGLint fTexCoordXformUniform;
Robert Phillips294870f2016-11-11 12:38:40 -0500614 } fMipmapPrograms[4];
615 sk_sp<GrGLBuffer> fMipmapProgramArrayBuffer;
brianosman33f6b3f2016-06-02 05:49:21 -0700616
Mike Klein31550db2017-06-06 23:29:53 +0000617 GrGLuint fStencilClipClearProgram;
618 sk_sp<GrGLBuffer> fStencilClipClearArrayBuffer;
bsalomon6dea83f2015-12-03 12:58:06 -0800619
Brian Salomonbf7b6202016-11-11 16:08:03 -0500620 static int TextureToCopyProgramIdx(GrTexture* texture) {
621 switch (texture->texturePriv().samplerType()) {
622 case kTexture2DSampler_GrSLType:
bsalomone5286e02016-01-14 09:24:09 -0800623 return 0;
Brian Salomona8f00022016-11-16 12:55:57 -0500624 case kITexture2DSampler_GrSLType:
bsalomone5286e02016-01-14 09:24:09 -0800625 return 1;
Brian Salomonbf7b6202016-11-11 16:08:03 -0500626 case kTexture2DRectSampler_GrSLType:
bsalomone5286e02016-01-14 09:24:09 -0800627 return 2;
Brian Salomonbf7b6202016-11-11 16:08:03 -0500628 case kTextureExternalSampler_GrSLType:
629 return 3;
bsalomone5286e02016-01-14 09:24:09 -0800630 default:
Brian Salomonbf7b6202016-11-11 16:08:03 -0500631 SkFAIL("Unexpected samper type");
bsalomone5286e02016-01-14 09:24:09 -0800632 return 0;
bsalomon7ea33f52015-11-22 14:51:00 -0800633 }
634 }
bsalomon6df86402015-06-01 10:41:49 -0700635
brianosman33f6b3f2016-06-02 05:49:21 -0700636 static int TextureSizeToMipmapProgramIdx(int width, int height) {
637 const bool wide = (width > 1) && SkToBool(width & 0x1);
638 const bool tall = (height > 1) && SkToBool(height & 0x1);
639 return (wide ? 0x2 : 0x0) | (tall ? 0x1 : 0x0);
640 }
641
Robert Phillips294870f2016-11-11 12:38:40 -0500642 float fHWMinSampleShading;
ethannicholas28ef4452016-03-25 09:26:03 -0700643
reed@google.comac10a2d2010-12-22 21:39:39 +0000644 typedef GrGpu INHERITED;
kkinnunenccdaa042014-08-20 01:36:23 -0700645 friend class GrGLPathRendering; // For accessing setTextureUnit.
csmartdaltona7f29642016-07-07 08:49:11 -0700646 friend class gr_instanced::GLInstancedRendering; // For accessing flushGLState.
reed@google.comac10a2d2010-12-22 21:39:39 +0000647};
648
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000649#endif