blob: d03ef781e18fed33f5d427667968d6fae6131561 [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
epoger@google.comec3ed6a2011-07-28 14:26:00 +00008
reed@google.comac10a2d2010-12-22 21:39:39 +00009#include "GrGpuGL.h"
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +000010#include "GrGLStencilBuffer.h"
bsalomon@google.com64aef2b2012-06-11 15:36:13 +000011#include "GrGLPath.h"
bsalomon@google.com6d003d12012-09-11 15:45:20 +000012#include "GrGLShaderBuilder.h"
bsalomon@google.coma3201942012-06-21 19:58:20 +000013#include "GrTemplates.h"
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +000014#include "GrTypes.h"
bsalomon@google.com3582bf92011-06-30 21:32:31 +000015#include "SkTemplates.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016
caryclark@google.comcf6285b2012-06-06 12:09:01 +000017static const GrGLuint GR_MAX_GLUINT = ~0U;
twiz@google.com0f31ca72011-03-18 17:38:11 +000018static const GrGLint GR_INVAL_GLINT = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000019
bsalomon@google.com0b77d682011-08-19 13:28:54 +000020#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +000021#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X)
bsalomon@google.com0b77d682011-08-19 13:28:54 +000022
bsalomon@google.com316f99232011-01-13 21:28:12 +000023// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000024// mucking with the state of any of the stages.
tomhudson@google.com93813632011-10-27 20:21:16 +000025static const int SPARE_TEX_UNIT = GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000026
reed@google.comac10a2d2010-12-22 21:39:39 +000027#define SKIP_CACHE_CHECK true
28
bsalomon@google.com4f3c2532012-01-19 16:16:52 +000029#if GR_GL_CHECK_ALLOC_WITH_GET_ERROR
30 #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface)
31 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call)
32 #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface)
rmistry@google.comfbfcd562012-08-23 18:09:54 +000033#else
bsalomon@google.com4f3c2532012-01-19 16:16:52 +000034 #define CLEAR_ERROR_BEFORE_ALLOC(iface)
35 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call)
36 #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR
37#endif
38
bsalomon@google.com4bcb0c62012-02-07 16:06:47 +000039
40///////////////////////////////////////////////////////////////////////////////
41
twiz@google.com0f31ca72011-03-18 17:38:11 +000042static const GrGLenum gXfermodeCoeff2Blend[] = {
43 GR_GL_ZERO,
44 GR_GL_ONE,
45 GR_GL_SRC_COLOR,
46 GR_GL_ONE_MINUS_SRC_COLOR,
47 GR_GL_DST_COLOR,
48 GR_GL_ONE_MINUS_DST_COLOR,
49 GR_GL_SRC_ALPHA,
50 GR_GL_ONE_MINUS_SRC_ALPHA,
51 GR_GL_DST_ALPHA,
52 GR_GL_ONE_MINUS_DST_ALPHA,
53 GR_GL_CONSTANT_COLOR,
54 GR_GL_ONE_MINUS_CONSTANT_COLOR,
55 GR_GL_CONSTANT_ALPHA,
56 GR_GL_ONE_MINUS_CONSTANT_ALPHA,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000057
58 // extended blend coeffs
59 GR_GL_SRC1_COLOR,
60 GR_GL_ONE_MINUS_SRC1_COLOR,
61 GR_GL_SRC1_ALPHA,
62 GR_GL_ONE_MINUS_SRC1_ALPHA,
reed@google.comac10a2d2010-12-22 21:39:39 +000063};
64
bsalomon@google.com271cffc2011-05-20 14:13:56 +000065bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
bsalomon@google.com080773c2011-03-15 19:09:25 +000066 static const bool gCoeffReferencesBlendConst[] = {
67 false,
68 false,
69 false,
70 false,
71 false,
72 false,
73 false,
74 false,
75 false,
76 false,
77 true,
78 true,
79 true,
80 true,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000081
82 // extended blend coeffs
83 false,
84 false,
85 false,
86 false,
bsalomon@google.com080773c2011-03-15 19:09:25 +000087 };
88 return gCoeffReferencesBlendConst[coeff];
bsalomon@google.com47059542012-06-06 20:51:20 +000089 GR_STATIC_ASSERT(kTotalGrBlendCoeffCount ==
90 GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
bsalomon@google.com271cffc2011-05-20 14:13:56 +000091
bsalomon@google.com47059542012-06-06 20:51:20 +000092 GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff);
93 GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff);
94 GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff);
95 GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff);
96 GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff);
97 GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff);
98 GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff);
99 GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff);
100 GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff);
101 GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff);
102 GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff);
103 GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff);
104 GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff);
105 GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff);
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000106
bsalomon@google.com47059542012-06-06 20:51:20 +0000107 GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff);
108 GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff);
109 GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff);
110 GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff);
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000111
112 // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
bsalomon@google.com47059542012-06-06 20:51:20 +0000113 GR_STATIC_ASSERT(kTotalGrBlendCoeffCount ==
114 GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
bsalomon@google.com080773c2011-03-15 19:09:25 +0000115}
116
reed@google.comac10a2d2010-12-22 21:39:39 +0000117///////////////////////////////////////////////////////////////////////////////
118
rileya@google.come38160c2012-07-03 18:03:04 +0000119static bool gPrintStartupSpew;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000120
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000121static bool fbo_test(const GrGLInterface* gl, int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000122
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000123 GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000124
twiz@google.com0f31ca72011-03-18 17:38:11 +0000125 GrGLuint testFBO;
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000126 GR_GL_CALL(gl, GenFramebuffers(1, &testFBO));
127 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000128 GrGLuint testRTTex;
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000129 GR_GL_CALL(gl, GenTextures(1, &testRTTex));
130 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000131 // some implementations require texture to be mip-map complete before
132 // FBO with level 0 bound as color attachment will be framebuffer complete.
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +0000133 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D,
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000134 GR_GL_TEXTURE_MIN_FILTER,
135 GR_GL_NEAREST));
136 GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
137 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
138 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
139 GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER,
140 GR_GL_COLOR_ATTACHMENT0,
141 GR_GL_TEXTURE_2D, testRTTex, 0));
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +0000142 GrGLenum status;
143 GR_GL_CALL_RET(gl, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000144 GR_GL_CALL(gl, DeleteFramebuffers(1, &testFBO));
145 GR_GL_CALL(gl, DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000146
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000147 return status == GR_GL_FRAMEBUFFER_COMPLETE;
reed@google.comac10a2d2010-12-22 21:39:39 +0000148}
149
robertphillips@google.com6177e692013-02-28 20:16:25 +0000150GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000151 : GrGpu(context)
robertphillips@google.com6177e692013-02-28 20:16:25 +0000152 , fGLContext(ctx) {
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000153
robertphillips@google.com6177e692013-02-28 20:16:25 +0000154 GrAssert(ctx.isInitialized());
tomhudson@google.com747bf292011-06-14 18:16:52 +0000155
bsalomon@google.combcce8922013-03-25 15:38:39 +0000156 fCaps.reset(SkRef(ctx.info().caps()));
157
robertphillips@google.com99a5ac02012-04-10 19:26:38 +0000158 fillInConfigRenderableTable();
159
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000160
robertphillips@google.com6177e692013-02-28 20:16:25 +0000161 GrGLClearErr(fGLContext.interface());
reed@google.comac10a2d2010-12-22 21:39:39 +0000162
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000163 if (gPrintStartupSpew) {
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000164 const GrGLubyte* ext;
165 GL_CALL_RET(ext, GetString(GR_GL_EXTENSIONS));
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +0000166 const GrGLubyte* vendor;
167 const GrGLubyte* renderer;
168 const GrGLubyte* version;
169 GL_CALL_RET(vendor, GetString(GR_GL_VENDOR));
170 GL_CALL_RET(renderer, GetString(GR_GL_RENDERER));
171 GL_CALL_RET(version, GetString(GR_GL_VERSION));
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000172 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
173 this);
174 GrPrintf("------ VENDOR %s\n", vendor);
175 GrPrintf("------ RENDERER %s\n", renderer);
176 GrPrintf("------ VERSION %s\n", version);
177 GrPrintf("------ EXTENSIONS\n %s \n", ext);
bsalomon@google.combcce8922013-03-25 15:38:39 +0000178 ctx.info().caps()->print();
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000179 }
180
robertphillips@google.com6177e692013-02-28 20:16:25 +0000181 fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContext()));
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000182
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000183 GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt);
184 GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kColorOverrideAttribIndexValue);
185 GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kCoverageOverrideAttribIndexValue);
186
bsalomon@google.comfe676522011-06-17 18:12:21 +0000187 fLastSuccessfulStencilFmtIdx = 0;
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000188 if (false) { // avoid bit rot, suppress warning
189 fbo_test(this->glInterface(), 0, 0);
190 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000191}
192
193GrGpuGL::~GrGpuGL() {
bsalomon@google.com9ba4fa62012-07-16 17:36:28 +0000194 if (0 != fHWProgramID) {
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000195 // detach the current program so there is no confusion on OpenGL's part
196 // that we want it to be deleted
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000197 GrAssert(fHWProgramID == fCurrentProgram->programID());
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000198 GL_CALL(UseProgram(0));
199 }
200
bsalomon@google.comc1d2a582012-06-01 15:08:19 +0000201 delete fProgramCache;
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000202
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000203 // This must be called by before the GrDrawTarget destructor
204 this->releaseGeometry();
bsalomon@google.com15b11df2011-09-16 21:18:29 +0000205 // This subclass must do this before the base class destructor runs
206 // since we will unref the GrGLInterface.
207 this->releaseResources();
reed@google.comac10a2d2010-12-22 21:39:39 +0000208}
209
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000210///////////////////////////////////////////////////////////////////////////////
211
robertphillips@google.com99a5ac02012-04-10 19:26:38 +0000212void GrGpuGL::fillInConfigRenderableTable() {
213
214 // OpenGL < 3.0
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000215 // no support for render targets unless the GL_ARB_framebuffer_object
216 // extension is supported (in which case we get ALPHA, RED, RG, RGB,
217 // RGBA (ALPHA8, RGBA4, RGBA8) for OpenGL > 1.1). Note that we
robertphillips@google.com99a5ac02012-04-10 19:26:38 +0000218 // probably don't get R8 in this case.
219
220 // OpenGL 3.0
221 // base color renderable: ALPHA, RED, RG, RGB, and RGBA
222 // sized derivatives: ALPHA8, R8, RGBA4, RGBA8
223
224 // >= OpenGL 3.1
225 // base color renderable: RED, RG, RGB, and RGBA
226 // sized derivatives: R8, RGBA4, RGBA8
227 // if the GL_ARB_compatibility extension is supported then we get back
228 // support for GL_ALPHA and ALPHA8
229
230 // GL_EXT_bgra adds BGRA render targets to any version
231
232 // ES 2.0
233 // color renderable: RGBA4, RGB5_A1, RGB565
234 // GL_EXT_texture_rg adds support for R8 as a color render target
235 // GL_OES_rgb8_rgba8 and/or GL_ARM_rgba8 adds support for RGBA8
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000236 // GL_EXT_texture_format_BGRA8888 and/or GL_APPLE_texture_format_BGRA8888 added BGRA support
robertphillips@google.com99a5ac02012-04-10 19:26:38 +0000237
238 if (kDesktop_GrGLBinding == this->glBinding()) {
239 // Post 3.0 we will get R8
240 // Prior to 3.0 we will get ALPHA8 (with GL_ARB_framebuffer_object)
241 if (this->glVersion() >= GR_GL_VER(3,0) ||
242 this->hasExtension("GL_ARB_framebuffer_object")) {
243 fConfigRenderSupport[kAlpha_8_GrPixelConfig] = true;
244 }
245 } else {
246 // On ES we can only hope for R8
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000247 fConfigRenderSupport[kAlpha_8_GrPixelConfig] =
robertphillips@google.com443e5a52012-04-30 20:01:21 +0000248 this->glCaps().textureRedSupport();
robertphillips@google.com99a5ac02012-04-10 19:26:38 +0000249 }
250
251 if (kDesktop_GrGLBinding != this->glBinding()) {
252 // only available in ES
253 fConfigRenderSupport[kRGB_565_GrPixelConfig] = true;
254 }
255
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000256 // Pre 3.0, Ganesh relies on either GL_ARB_framebuffer_object or
robertphillips@google.com99a5ac02012-04-10 19:26:38 +0000257 // GL_EXT_framebuffer_object for FBO support. Both of these
258 // allow RGBA4 render targets so this is always supported.
259 fConfigRenderSupport[kRGBA_4444_GrPixelConfig] = true;
260
261 if (this->glCaps().rgba8RenderbufferSupport()) {
bsalomon@google.com0342a852012-08-20 19:22:38 +0000262 fConfigRenderSupport[kRGBA_8888_GrPixelConfig] = true;
robertphillips@google.com99a5ac02012-04-10 19:26:38 +0000263 }
264
265 if (this->glCaps().bgraFormatSupport()) {
bsalomon@google.com0342a852012-08-20 19:22:38 +0000266 fConfigRenderSupport[kBGRA_8888_GrPixelConfig] = true;
robertphillips@google.com99a5ac02012-04-10 19:26:38 +0000267 }
robertphillips@google.com99a5ac02012-04-10 19:26:38 +0000268}
269
bsalomon@google.com9c680582013-02-06 18:17:50 +0000270namespace {
271GrPixelConfig preferred_pixel_ops_config(GrPixelConfig config) {
272 if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && kRGBA_8888_GrPixelConfig == config) {
273 return kBGRA_8888_GrPixelConfig;
bsalomon@google.coma85449d2011-11-19 02:36:05 +0000274 } else {
275 return config;
276 }
277}
bsalomon@google.com9c680582013-02-06 18:17:50 +0000278}
279
280GrPixelConfig GrGpuGL::preferredReadPixelsConfig(GrPixelConfig config) const {
281 return preferred_pixel_ops_config(config);
282}
bsalomon@google.coma85449d2011-11-19 02:36:05 +0000283
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000284GrPixelConfig GrGpuGL::preferredWritePixelsConfig(GrPixelConfig config) const {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000285 return preferred_pixel_ops_config(config);
286}
287
288bool GrGpuGL::canWriteTexturePixels(const GrTexture* texture, GrPixelConfig srcConfig) const {
289 if (kIndex_8_GrPixelConfig == srcConfig || kIndex_8_GrPixelConfig == texture->config()) {
290 return false;
291 }
292 if (srcConfig != texture->config() && kES2_GrGLBinding == this->glBinding()) {
293 // In general ES2 requires the internal format of the texture and the format of the src
294 // pixels to match. However, It may or may not be possible to upload BGRA data to a RGBA
295 // texture. It depends upon which extension added BGRA. The Apple extension allows it
296 // (BGRA's internal format is RGBA) while the EXT extension does not (BGRA is its own
297 // internal format).
298 if (this->glCaps().bgraFormatSupport() &&
299 !this->glCaps().bgraIsInternalFormat() &&
300 kBGRA_8888_GrPixelConfig == srcConfig &&
301 kRGBA_8888_GrPixelConfig == texture->config()) {
302 return true;
303 } else {
304 return false;
305 }
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000306 } else {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000307 return true;
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000308 }
309}
310
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000311bool GrGpuGL::fullReadPixelsIsFasterThanPartial() const {
312 return SkToBool(GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL);
313}
314
bsalomon@google.com1bf1c212011-11-05 12:18:58 +0000315void GrGpuGL::onResetContext() {
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000316
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000317 // we don't use the zb at all
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000318 GL_CALL(Disable(GR_GL_DEPTH_TEST));
319 GL_CALL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000320
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000321 fHWDrawFace = GrDrawState::kInvalid_DrawFace;
322 fHWDitherEnabled = kUnknown_TriState;
reed@google.comac10a2d2010-12-22 21:39:39 +0000323
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000324 if (kDesktop_GrGLBinding == this->glBinding()) {
bsalomon@google.com469d0dd2012-05-21 20:14:29 +0000325 // Desktop-only state that we never change
bsalomon@google.com2b1b8c02013-02-28 22:06:02 +0000326 if (!this->glCaps().isCoreProfile()) {
327 GL_CALL(Disable(GR_GL_POINT_SMOOTH));
328 GL_CALL(Disable(GR_GL_LINE_SMOOTH));
329 GL_CALL(Disable(GR_GL_POLYGON_SMOOTH));
330 GL_CALL(Disable(GR_GL_POLYGON_STIPPLE));
331 GL_CALL(Disable(GR_GL_COLOR_LOGIC_OP));
332 GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
333 }
commit-bot@chromium.orgdd4400b2013-03-21 19:58:22 +0000334 // The windows NVIDIA driver has GL_ARB_imaging in the extension string when using a core
335 // profile. This seems like a bug since the core spec removes any mention of GL_ARB_imaging.
336 if (this->glCaps().imagingSupport() && !this->glCaps().isCoreProfile()) {
bsalomon@google.come76b7cc2012-06-18 12:47:06 +0000337 GL_CALL(Disable(GR_GL_COLOR_TABLE));
338 }
bsalomon@google.com469d0dd2012-05-21 20:14:29 +0000339 GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
340 // Since ES doesn't support glPointSize at all we always use the VS to
341 // set the point size
342 GL_CALL(Enable(GR_GL_VERTEX_PROGRAM_POINT_SIZE));
343
344 // We should set glPolygonMode(FRONT_AND_BACK,FILL) here, too. It isn't
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000345 // currently part of our gl interface. There are probably others as
bsalomon@google.com469d0dd2012-05-21 20:14:29 +0000346 // well.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000347 }
bsalomon@google.com4d5f3fe2012-05-21 17:11:44 +0000348 fHWAAState.invalidate();
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000349 fHWWriteToColor = kUnknown_TriState;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000350
reed@google.comac10a2d2010-12-22 21:39:39 +0000351 // we only ever use lines in hairline mode
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000352 GL_CALL(LineWidth(1));
reed@google.comac10a2d2010-12-22 21:39:39 +0000353
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000354 // invalid
bsalomon@google.com49209392012-06-05 15:13:46 +0000355 fHWActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000356
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +0000357 fHWBlendState.invalidate();
bsalomon@google.com080773c2011-03-15 19:09:25 +0000358
tomhudson@google.com93813632011-10-27 20:21:16 +0000359 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc811ea32012-05-21 15:33:09 +0000360 fHWBoundTextures[s] = NULL;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000361 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000362
bsalomon@google.coma3201942012-06-21 19:58:20 +0000363 fHWScissorSettings.invalidate();
robertphillips@google.com730ebe52012-04-16 16:33:13 +0000364
bsalomon@google.coma3201942012-06-21 19:58:20 +0000365 fHWViewport.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000366
bsalomon@google.com457b8a32012-05-21 21:19:58 +0000367 fHWStencilSettings.invalidate();
bsalomon@google.coma3201942012-06-21 19:58:20 +0000368 fHWStencilTestEnabled = kUnknown_TriState;
robertphillips@google.com730ebe52012-04-16 16:33:13 +0000369
bsalomon@google.com880b8fc2013-02-19 20:17:28 +0000370 fHWGeometryState.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000371
bsalomon@google.comc811ea32012-05-21 15:33:09 +0000372 fHWBoundRenderTarget = NULL;
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000373
bsalomon@google.com6a51dcb2013-02-13 16:03:51 +0000374 fHWPathStencilMatrixState.invalidate();
bsalomon@google.combcce8922013-03-25 15:38:39 +0000375 if (this->caps()->pathStencilingSupport()) {
bsalomon@google.com05a718c2012-06-29 14:01:53 +0000376 // we don't use the model view matrix.
377 GL_CALL(MatrixMode(GR_GL_MODELVIEW));
378 GL_CALL(LoadIdentity());
379 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000380
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000381 // we assume these values
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000382 if (this->glCaps().unpackRowLengthSupport()) {
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000383 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
384 }
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000385 if (this->glCaps().packRowLengthSupport()) {
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000386 GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
387 }
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000388 if (this->glCaps().unpackFlipYSupport()) {
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000389 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
390 }
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000391 if (this->glCaps().packFlipYSupport()) {
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000392 GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
393 }
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000394
bsalomon@google.com5739d2c2012-05-31 15:07:19 +0000395 fHWProgramID = 0;
bsalomon@google.com91207482013-02-12 21:45:24 +0000396 fSharedGLProgramState.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000397}
398
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000399namespace {
400
401GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
402 // By default, GrRenderTargets are GL's normal orientation so that they
403 // can be drawn to by the outside world without the client having
404 // to render upside down.
405 if (kDefault_GrSurfaceOrigin == origin) {
406 return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
407 } else {
408 return origin;
409 }
410}
411
412}
413
bsalomon@google.com16e3dde2012-10-25 18:43:28 +0000414GrTexture* GrGpuGL::onWrapBackendTexture(const GrBackendTextureDesc& desc) {
bsalomon@google.com16e3dde2012-10-25 18:43:28 +0000415 if (!this->configToGLFormats(desc.fConfig, false, NULL, NULL, NULL)) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000416 return NULL;
417 }
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000418
robertphillips@google.comb72e5d32012-10-30 15:18:10 +0000419 if (0 == desc.fTextureHandle) {
420 return NULL;
421 }
422
bsalomon@google.combcce8922013-03-25 15:38:39 +0000423 int maxSize = this->caps()->maxTextureSize();
robertphillips@google.comb72e5d32012-10-30 15:18:10 +0000424 if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
425 return NULL;
426 }
427
428 GrGLTexture::Desc glTexDesc;
bsalomon@google.com16e3dde2012-10-25 18:43:28 +0000429 // next line relies on GrBackendTextureDesc's flags matching GrTexture's
robertphillips@google.com32716282012-06-04 12:48:45 +0000430 glTexDesc.fFlags = (GrTextureFlags) desc.fFlags;
bsalomon@google.com99621082011-11-15 16:47:16 +0000431 glTexDesc.fWidth = desc.fWidth;
432 glTexDesc.fHeight = desc.fHeight;
bsalomon@google.come269f212011-11-07 13:29:52 +0000433 glTexDesc.fConfig = desc.fConfig;
robertphillips@google.com32716282012-06-04 12:48:45 +0000434 glTexDesc.fSampleCnt = desc.fSampleCnt;
bsalomon@google.come269f212011-11-07 13:29:52 +0000435 glTexDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle);
bsalomon@google.com72830222013-01-23 20:25:22 +0000436 glTexDesc.fIsWrapped = true;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000437 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrBackendTextureFlag);
438 // FIXME: this should be calling resolve_origin(), but Chrome code is currently
439 // assuming the old behaviour, which is that backend textures are always
440 // BottomLeft, even for non-RT's. Once Chrome is fixed, change this to:
441 // glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
442 if (kDefault_GrSurfaceOrigin == desc.fOrigin) {
443 glTexDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
444 } else {
445 glTexDesc.fOrigin = desc.fOrigin;
446 }
bsalomon@google.come269f212011-11-07 13:29:52 +0000447
448 GrGLTexture* texture = NULL;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000449 if (renderTarget) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000450 GrGLRenderTarget::Desc glRTDesc;
451 glRTDesc.fRTFBOID = 0;
452 glRTDesc.fTexFBOID = 0;
453 glRTDesc.fMSColorRenderbufferID = 0;
bsalomon@google.come269f212011-11-07 13:29:52 +0000454 glRTDesc.fConfig = desc.fConfig;
455 glRTDesc.fSampleCnt = desc.fSampleCnt;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000456 glRTDesc.fOrigin = glTexDesc.fOrigin;
bsalomon@google.com99621082011-11-15 16:47:16 +0000457 if (!this->createRenderTargetObjects(glTexDesc.fWidth,
458 glTexDesc.fHeight,
bsalomon@google.come269f212011-11-07 13:29:52 +0000459 glTexDesc.fTextureID,
460 &glRTDesc)) {
461 return NULL;
462 }
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000463 texture = SkNEW_ARGS(GrGLTexture, (this, glTexDesc, glRTDesc));
bsalomon@google.come269f212011-11-07 13:29:52 +0000464 } else {
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000465 texture = SkNEW_ARGS(GrGLTexture, (this, glTexDesc));
bsalomon@google.come269f212011-11-07 13:29:52 +0000466 }
467 if (NULL == texture) {
468 return NULL;
469 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000470
bsalomon@google.come269f212011-11-07 13:29:52 +0000471 this->setSpareTextureUnit();
472 return texture;
473}
474
bsalomon@google.com16e3dde2012-10-25 18:43:28 +0000475GrRenderTarget* GrGpuGL::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000476 GrGLRenderTarget::Desc glDesc;
477 glDesc.fConfig = desc.fConfig;
478 glDesc.fRTFBOID = static_cast<GrGLuint>(desc.fRenderTargetHandle);
479 glDesc.fMSColorRenderbufferID = 0;
480 glDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
481 glDesc.fSampleCnt = desc.fSampleCnt;
bsalomon@google.com72830222013-01-23 20:25:22 +0000482 glDesc.fIsWrapped = true;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000483 glDesc.fOrigin = desc.fOrigin;
484 if (glDesc.fRTFBOID == 0) {
485 GrAssert(desc.fOrigin == kBottomLeft_GrSurfaceOrigin);
486 }
487
488 glDesc.fOrigin = resolve_origin(desc.fOrigin, true);
bsalomon@google.come269f212011-11-07 13:29:52 +0000489 GrGLIRect viewport;
490 viewport.fLeft = 0;
491 viewport.fBottom = 0;
492 viewport.fWidth = desc.fWidth;
493 viewport.fHeight = desc.fHeight;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000494
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000495 GrRenderTarget* tgt = SkNEW_ARGS(GrGLRenderTarget,
496 (this, glDesc, viewport));
bsalomon@google.come269f212011-11-07 13:29:52 +0000497 if (desc.fStencilBits) {
498 GrGLStencilBuffer::Format format;
499 format.fInternalFormat = GrGLStencilBuffer::kUnknownInternalFormat;
500 format.fPacked = false;
501 format.fStencilBits = desc.fStencilBits;
502 format.fTotalBits = desc.fStencilBits;
bsalomon@google.com1f0f1a32013-01-23 21:32:32 +0000503 static const bool kIsSBWrapped = false;
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000504 GrGLStencilBuffer* sb = SkNEW_ARGS(GrGLStencilBuffer,
505 (this,
bsalomon@google.com1f0f1a32013-01-23 21:32:32 +0000506 kIsSBWrapped,
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000507 0,
508 desc.fWidth,
509 desc.fHeight,
510 desc.fSampleCnt,
511 format));
bsalomon@google.come269f212011-11-07 13:29:52 +0000512 tgt->setStencilBuffer(sb);
513 sb->unref();
514 }
515 return tgt;
516}
517
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000518////////////////////////////////////////////////////////////////////////////////
519
bsalomon@google.com9c680582013-02-06 18:17:50 +0000520bool GrGpuGL::onWriteTexturePixels(GrTexture* texture,
bsalomon@google.com6f379512011-11-16 20:36:03 +0000521 int left, int top, int width, int height,
522 GrPixelConfig config, const void* buffer,
523 size_t rowBytes) {
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000524 if (NULL == buffer) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000525 return false;
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000526 }
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000527 GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
528
bsalomon@google.com6f379512011-11-16 20:36:03 +0000529 this->setSpareTextureUnit();
530 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID()));
531 GrGLTexture::Desc desc;
robertphillips@google.com32716282012-06-04 12:48:45 +0000532 desc.fFlags = glTex->desc().fFlags;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000533 desc.fWidth = glTex->width();
534 desc.fHeight = glTex->height();
robertphillips@google.com32716282012-06-04 12:48:45 +0000535 desc.fConfig = glTex->config();
536 desc.fSampleCnt = glTex->desc().fSampleCnt;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000537 desc.fTextureID = glTex->textureID();
bsalomon@google.com2d0bade2012-10-26 19:01:17 +0000538 desc.fOrigin = glTex->origin();
bsalomon@google.com9d6cfd82011-11-05 13:25:21 +0000539
bsalomon@google.com9c680582013-02-06 18:17:50 +0000540 return this->uploadTexData(desc, false,
541 left, top, width, height,
542 config, buffer, rowBytes);
bsalomon@google.com6f379512011-11-16 20:36:03 +0000543}
544
bsalomon@google.coma85449d2011-11-19 02:36:05 +0000545namespace {
546bool adjust_pixel_ops_params(int surfaceWidth,
547 int surfaceHeight,
548 size_t bpp,
549 int* left, int* top, int* width, int* height,
550 const void** data,
551 size_t* rowBytes) {
552 if (!*rowBytes) {
553 *rowBytes = *width * bpp;
554 }
555
556 GrIRect subRect = GrIRect::MakeXYWH(*left, *top, *width, *height);
557 GrIRect bounds = GrIRect::MakeWH(surfaceWidth, surfaceHeight);
558
559 if (!subRect.intersect(bounds)) {
560 return false;
561 }
562 *data = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>(*data) +
563 (subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp);
564
565 *left = subRect.fLeft;
566 *top = subRect.fTop;
567 *width = subRect.width();
568 *height = subRect.height();
569 return true;
570}
571}
572
bsalomon@google.com136f55b2011-11-28 18:34:44 +0000573bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
574 bool isNewTexture,
bsalomon@google.com6f379512011-11-16 20:36:03 +0000575 int left, int top, int width, int height,
576 GrPixelConfig dataConfig,
577 const void* data,
578 size_t rowBytes) {
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000579 GrAssert(NULL != data || isNewTexture);
bsalomon@google.coma85449d2011-11-19 02:36:05 +0000580
581 size_t bpp = GrBytesPerPixel(dataConfig);
582 if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top,
583 &width, &height, &data, &rowBytes)) {
bsalomon@google.com136f55b2011-11-28 18:34:44 +0000584 return false;
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000585 }
bsalomon@google.coma85449d2011-11-19 02:36:05 +0000586 size_t trimRowBytes = width * bpp;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000587
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000588 // in case we need a temporary, trimmed copy of the src pixels
589 SkAutoSMalloc<128 * 128> tempStorage;
590
bsalomon@google.com313f0192012-07-10 17:21:02 +0000591 // paletted textures cannot be partially updated
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000592 bool useTexStorage = isNewTexture &&
bsalomon@google.com313f0192012-07-10 17:21:02 +0000593 desc.fConfig != kIndex_8_GrPixelConfig &&
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000594 this->glCaps().texStorageSupport();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000595
bsalomon@google.com313f0192012-07-10 17:21:02 +0000596 if (useTexStorage && kDesktop_GrGLBinding == this->glBinding()) {
597 // 565 is not a sized internal format on desktop GL. So on desktop with
598 // 565 we always use an unsized internal format to let the system pick
599 // the best sized format to convert the 565 data to. Since TexStorage
600 // only allows sized internal formats we will instead use TexImage2D.
601 useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig;
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000602 }
603
604 GrGLenum internalFormat;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000605 GrGLenum externalFormat;
606 GrGLenum externalType;
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000607 // glTexStorage requires sized internal formats on both desktop and ES. ES
608 // glTexImage requires an unsized format.
609 if (!this->configToGLFormats(dataConfig, useTexStorage, &internalFormat,
610 &externalFormat, &externalType)) {
bsalomon@google.com136f55b2011-11-28 18:34:44 +0000611 return false;
bsalomon@google.com6f379512011-11-16 20:36:03 +0000612 }
613
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000614 if (!isNewTexture && GR_GL_PALETTE8_RGBA8 == internalFormat) {
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +0000615 // paletted textures cannot be updated
616 return false;
617 }
618
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000619 /*
bsalomon@google.com6f379512011-11-16 20:36:03 +0000620 * check whether to allocate a temporary buffer for flipping y or
621 * because our srcData has extra bytes past each row. If so, we need
622 * to trim those off here, since GL ES may not let us specify
623 * GL_UNPACK_ROW_LENGTH.
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000624 */
bsalomon@google.com6f379512011-11-16 20:36:03 +0000625 bool restoreGLRowLength = false;
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000626 bool swFlipY = false;
627 bool glFlipY = false;
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000628 if (NULL != data) {
senorblanco@chromium.orgef5dbe12013-01-28 16:42:38 +0000629 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000630 if (this->glCaps().unpackFlipYSupport()) {
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000631 glFlipY = true;
632 } else {
633 swFlipY = true;
634 }
635 }
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000636 if (this->glCaps().unpackRowLengthSupport() && !swFlipY) {
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000637 // can't use this for flipping, only non-neg values allowed. :(
638 if (rowBytes != trimRowBytes) {
639 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
640 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
641 restoreGLRowLength = true;
642 }
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000643 } else {
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000644 if (trimRowBytes != rowBytes || swFlipY) {
645 // copy data into our new storage, skipping the trailing bytes
646 size_t trimSize = height * trimRowBytes;
647 const char* src = (const char*)data;
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000648 if (swFlipY) {
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000649 src += (height - 1) * rowBytes;
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000650 }
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000651 char* dst = (char*)tempStorage.reset(trimSize);
652 for (int y = 0; y < height; y++) {
653 memcpy(dst, src, trimRowBytes);
654 if (swFlipY) {
655 src -= rowBytes;
656 } else {
657 src += rowBytes;
658 }
659 dst += trimRowBytes;
660 }
661 // now point data to our copied version
662 data = tempStorage.get();
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000663 }
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000664 }
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000665 if (glFlipY) {
666 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE));
667 }
668 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp)));
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000669 }
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000670 bool succeeded = true;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000671 if (isNewTexture &&
bsalomon@google.com136f55b2011-11-28 18:34:44 +0000672 0 == left && 0 == top &&
bsalomon@google.coma85449d2011-11-19 02:36:05 +0000673 desc.fWidth == width && desc.fHeight == height) {
bsalomon@google.com4f3c2532012-01-19 16:16:52 +0000674 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000675 if (useTexStorage) {
676 // We never resize or change formats of textures. We don't use
677 // mipmaps currently.
bsalomon@google.com4f3c2532012-01-19 16:16:52 +0000678 GL_ALLOC_CALL(this->glInterface(),
679 TexStorage2D(GR_GL_TEXTURE_2D,
680 1, // levels
681 internalFormat,
682 desc.fWidth, desc.fHeight));
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +0000683 } else {
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000684 if (GR_GL_PALETTE8_RGBA8 == internalFormat) {
685 GrGLsizei imageSize = desc.fWidth * desc.fHeight +
686 kGrColorTableSize;
bsalomon@google.com4f3c2532012-01-19 16:16:52 +0000687 GL_ALLOC_CALL(this->glInterface(),
688 CompressedTexImage2D(GR_GL_TEXTURE_2D,
689 0, // level
690 internalFormat,
691 desc.fWidth, desc.fHeight,
692 0, // border
693 imageSize,
694 data));
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000695 } else {
bsalomon@google.com4f3c2532012-01-19 16:16:52 +0000696 GL_ALLOC_CALL(this->glInterface(),
697 TexImage2D(GR_GL_TEXTURE_2D,
698 0, // level
699 internalFormat,
700 desc.fWidth, desc.fHeight,
701 0, // border
702 externalFormat, externalType,
703 data));
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000704 }
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +0000705 }
bsalomon@google.com4f3c2532012-01-19 16:16:52 +0000706 GrGLenum error = CHECK_ALLOC_ERROR(this->glInterface());
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000707 if (error != GR_GL_NO_ERROR) {
708 succeeded = false;
709 } else {
710 // if we have data and we used TexStorage to create the texture, we
711 // now upload with TexSubImage.
712 if (NULL != data && useTexStorage) {
713 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D,
714 0, // level
715 left, top,
716 width, height,
717 externalFormat, externalType,
718 data));
719 }
bsalomon@google.com136f55b2011-11-28 18:34:44 +0000720 }
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000721 } else {
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000722 if (swFlipY || glFlipY) {
bsalomon@google.com6f379512011-11-16 20:36:03 +0000723 top = desc.fHeight - (top + height);
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000724 }
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000725 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D,
726 0, // level
727 left, top,
728 width, height,
bsalomon@google.com6f379512011-11-16 20:36:03 +0000729 externalFormat, externalType, data));
730 }
731
732 if (restoreGLRowLength) {
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000733 GrAssert(this->glCaps().unpackRowLengthSupport());
bsalomon@google.com6f379512011-11-16 20:36:03 +0000734 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000735 }
bsalomon@google.com8ef3fd02011-11-21 15:53:13 +0000736 if (glFlipY) {
737 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE));
738 }
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000739 return succeeded;
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000740}
741
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000742namespace {
robertphillips@google.com6177e692013-02-28 20:16:25 +0000743bool renderbuffer_storage_msaa(GrGLContext& ctx,
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000744 int sampleCount,
745 GrGLenum format,
746 int width, int height) {
robertphillips@google.com6177e692013-02-28 20:16:25 +0000747 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface());
bsalomon@google.combcce8922013-03-25 15:38:39 +0000748 GrAssert(GrGLCaps::kNone_MSFBOType != ctx.info().caps()->msFBOType());
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000749 bool created = false;
750 if (GrGLCaps::kNVDesktop_CoverageAAType ==
bsalomon@google.combcce8922013-03-25 15:38:39 +0000751 ctx.info().caps()->coverageAAType()) {
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000752 const GrGLCaps::MSAACoverageMode& mode =
bsalomon@google.combcce8922013-03-25 15:38:39 +0000753 ctx.info().caps()->getMSAACoverageMode(sampleCount);
robertphillips@google.com6177e692013-02-28 20:16:25 +0000754 GL_ALLOC_CALL(ctx.interface(),
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000755 RenderbufferStorageMultisampleCoverage(GR_GL_RENDERBUFFER,
756 mode.fCoverageSampleCnt,
757 mode.fColorSampleCnt,
758 format,
759 width, height));
robertphillips@google.com6177e692013-02-28 20:16:25 +0000760 created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctx.interface()));
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000761 }
762 if (!created) {
robertphillips@google.com6177e692013-02-28 20:16:25 +0000763 GL_ALLOC_CALL(ctx.interface(),
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000764 RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
765 sampleCount,
766 format,
767 width, height));
robertphillips@google.com6177e692013-02-28 20:16:25 +0000768 created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctx.interface()));
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000769 }
770 return created;
771}
772}
773
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000774bool GrGpuGL::createRenderTargetObjects(int width, int height,
775 GrGLuint texID,
776 GrGLRenderTarget::Desc* desc) {
777 desc->fMSColorRenderbufferID = 0;
778 desc->fRTFBOID = 0;
779 desc->fTexFBOID = 0;
bsalomon@google.com72830222013-01-23 20:25:22 +0000780 desc->fIsWrapped = false;
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000781
782 GrGLenum status;
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000783
bsalomon@google.comab15d612011-08-09 12:57:56 +0000784 GrGLenum msColorFormat = 0; // suppress warning
785
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000786 GL_CALL(GenFramebuffers(1, &desc->fTexFBOID));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000787 if (!desc->fTexFBOID) {
788 goto FAILED;
789 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000790
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000791
bsalomon@google.comf3a60c02013-03-19 19:06:09 +0000792 // If we are using multisampling we will create two FBOS. We render to one and then resolve to
793 // the texture bound to the other. The exception is the IMG multisample extension. With this
794 // extension the texture is multisampled when rendered to and then auto-resolves it when it is
795 // rendered from.
796 if (desc->fSampleCnt > 0 && GrGLCaps::kImaginationES_MSFBOType != this->glCaps().msFBOType()) {
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000797 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
bsalomon@google.come269f212011-11-07 13:29:52 +0000798 goto FAILED;
799 }
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000800 GL_CALL(GenFramebuffers(1, &desc->fRTFBOID));
801 GL_CALL(GenRenderbuffers(1, &desc->fMSColorRenderbufferID));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000802 if (!desc->fRTFBOID ||
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000803 !desc->fMSColorRenderbufferID ||
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000804 !this->configToGLFormats(desc->fConfig,
805 // GLES requires sized internal formats
806 kES2_GrGLBinding == this->glBinding(),
807 &msColorFormat, NULL, NULL)) {
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000808 goto FAILED;
809 }
810 } else {
811 desc->fRTFBOID = desc->fTexFBOID;
812 }
813
bsalomon@google.com0e9b41a2012-01-04 22:11:43 +0000814 // below here we may bind the FBO
bsalomon@google.comc811ea32012-05-21 15:33:09 +0000815 fHWBoundRenderTarget = NULL;
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000816 if (desc->fRTFBOID != desc->fTexFBOID) {
bsalomon@google.com13ac3a32013-01-09 23:29:39 +0000817 GrAssert(desc->fSampleCnt > 0);
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000818 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER,
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000819 desc->fMSColorRenderbufferID));
robertphillips@google.com6177e692013-02-28 20:16:25 +0000820 if (!renderbuffer_storage_msaa(fGLContext,
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000821 desc->fSampleCnt,
822 msColorFormat,
823 width, height)) {
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000824 goto FAILED;
825 }
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000826 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fRTFBOID));
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000827 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000828 GR_GL_COLOR_ATTACHMENT0,
829 GR_GL_RENDERBUFFER,
830 desc->fMSColorRenderbufferID));
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000831 if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) {
bsalomon@google.com4bcb0c62012-02-07 16:06:47 +0000832 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
833 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
834 goto FAILED;
835 }
bsalomon@google.combcce8922013-03-25 15:38:39 +0000836 fGLContext.info().caps()->markConfigAsValidColorAttachment(desc->fConfig);
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000837 }
838 }
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000839 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000840
bsalomon@google.comf3a60c02013-03-19 19:06:09 +0000841 if (GrGLCaps::kImaginationES_MSFBOType == this->glCaps().msFBOType() && desc->fSampleCnt > 0) {
842 GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER,
843 GR_GL_COLOR_ATTACHMENT0,
844 GR_GL_TEXTURE_2D,
845 texID, 0, desc->fSampleCnt));
846 } else {
847 GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
848 GR_GL_COLOR_ATTACHMENT0,
849 GR_GL_TEXTURE_2D,
850 texID, 0));
851 }
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000852 if (!this->glCaps().isConfigVerifiedColorAttachment(desc->fConfig)) {
bsalomon@google.com4bcb0c62012-02-07 16:06:47 +0000853 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
854 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
855 goto FAILED;
856 }
bsalomon@google.combcce8922013-03-25 15:38:39 +0000857 fGLContext.info().caps()->markConfigAsValidColorAttachment(desc->fConfig);
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000858 }
859
860 return true;
861
862FAILED:
863 if (desc->fMSColorRenderbufferID) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000864 GL_CALL(DeleteRenderbuffers(1, &desc->fMSColorRenderbufferID));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000865 }
866 if (desc->fRTFBOID != desc->fTexFBOID) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000867 GL_CALL(DeleteFramebuffers(1, &desc->fRTFBOID));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000868 }
869 if (desc->fTexFBOID) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000870 GL_CALL(DeleteFramebuffers(1, &desc->fTexFBOID));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000871 }
872 return false;
873}
874
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000875// good to set a break-point here to know when createTexture fails
876static GrTexture* return_null_texture() {
877// GrAssert(!"null texture");
878 return NULL;
879}
880
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000881#if 0 && GR_DEBUG
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000882static size_t as_size_t(int x) {
883 return x;
884}
885#endif
886
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000887GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000888 const void* srcData,
889 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000890
bsalomon@google.com5bfc2172011-07-29 20:29:05 +0000891 GrGLTexture::Desc glTexDesc;
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000892 GrGLRenderTarget::Desc glRTDesc;
reed@google.comac10a2d2010-12-22 21:39:39 +0000893
bsalomon@google.com78d6cf92012-01-30 18:09:31 +0000894 // Attempt to catch un- or wrongly initialized sample counts;
895 GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000896 // We fail if the MSAA was requested and is not available.
897 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt) {
898 //GrPrintf("MSAA RT requested but not supported on this platform.");
899 return return_null_texture();
900 }
901 // If the sample count exceeds the max then we clamp it.
bsalomon@google.combcce8922013-03-25 15:38:39 +0000902 glTexDesc.fSampleCnt = GrMin(desc.fSampleCnt, this->caps()->maxSampleCount());
bsalomon@google.com78d6cf92012-01-30 18:09:31 +0000903
robertphillips@google.com32716282012-06-04 12:48:45 +0000904 glTexDesc.fFlags = desc.fFlags;
bsalomon@google.com99621082011-11-15 16:47:16 +0000905 glTexDesc.fWidth = desc.fWidth;
906 glTexDesc.fHeight = desc.fHeight;
bsalomon@google.com78d6cf92012-01-30 18:09:31 +0000907 glTexDesc.fConfig = desc.fConfig;
bsalomon@google.com72830222013-01-23 20:25:22 +0000908 glTexDesc.fIsWrapped = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000909
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000910 glRTDesc.fMSColorRenderbufferID = 0;
911 glRTDesc.fRTFBOID = 0;
912 glRTDesc.fTexFBOID = 0;
bsalomon@google.com72830222013-01-23 20:25:22 +0000913 glRTDesc.fIsWrapped = false;
bsalomon@google.com64c4fe42011-11-05 14:51:01 +0000914 glRTDesc.fConfig = glTexDesc.fConfig;
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000915
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000916 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000917
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000918 glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
919 glRTDesc.fOrigin = glTexDesc.fOrigin;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000920
bsalomon@google.com8a70eef2013-03-19 13:58:55 +0000921 glRTDesc.fSampleCnt = glTexDesc.fSampleCnt;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000922 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() &&
bsalomon@google.com78d6cf92012-01-30 18:09:31 +0000923 desc.fSampleCnt) {
bsalomon@google.com945bbe12012-06-15 14:30:34 +0000924 //GrPrintf("MSAA RT requested but not supported on this platform.");
925 return return_null_texture();
reed@google.comac10a2d2010-12-22 21:39:39 +0000926 }
927
reed@google.comac10a2d2010-12-22 21:39:39 +0000928 if (renderTarget) {
bsalomon@google.combcce8922013-03-25 15:38:39 +0000929 int maxRTSize = this->caps()->maxRenderTargetSize();
930 if (glTexDesc.fWidth > maxRTSize || glTexDesc.fHeight > maxRTSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000931 return return_null_texture();
932 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000933 }
934
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000935 GL_CALL(GenTextures(1, &glTexDesc.fTextureID));
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000936 if (renderTarget && this->glCaps().textureUsageSupport()) {
bsalomon@google.com07dd2bf2011-12-09 19:40:36 +0000937 // provides a hint about how this texture will be used
938 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
939 GR_GL_TEXTURE_USAGE,
940 GR_GL_FRAMEBUFFER_ATTACHMENT));
941 }
bsalomon@google.com5bfc2172011-07-29 20:29:05 +0000942 if (!glTexDesc.fTextureID) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000943 return return_null_texture();
944 }
945
bsalomon@google.com71f341a2011-08-01 13:36:00 +0000946 this->setSpareTextureUnit();
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000947 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID));
bsalomon@google.come269f212011-11-07 13:29:52 +0000948
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000949 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
950 // drivers have a bug where an FBO won't be complete if it includes a
951 // texture that is not mipmap complete (considering the filter in use).
952 GrGLTexture::TexParams initialTexParams;
953 // we only set a subset here so invalidate first
954 initialTexParams.invalidate();
955 initialTexParams.fFilter = GR_GL_NEAREST;
956 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE;
957 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE;
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000958 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
959 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000960 initialTexParams.fFilter));
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000961 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
962 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000963 initialTexParams.fFilter));
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000964 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
965 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000966 initialTexParams.fWrapS));
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000967 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
968 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000969 initialTexParams.fWrapT));
bsalomon@google.comb1d14fd2011-12-09 18:41:34 +0000970 if (!this->uploadTexData(glTexDesc, true, 0, 0,
971 glTexDesc.fWidth, glTexDesc.fHeight,
972 desc.fConfig, srcData, rowBytes)) {
973 GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID));
974 return return_null_texture();
bsalomon@google.com6f379512011-11-16 20:36:03 +0000975 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000976
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000977 GrGLTexture* tex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000978 if (renderTarget) {
robertphillips@google.comba0cc3e2012-03-26 17:58:35 +0000979 // unbind the texture from the texture unit before binding it to the frame buffer
980 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0));
981
bsalomon@google.com99621082011-11-15 16:47:16 +0000982 if (!this->createRenderTargetObjects(glTexDesc.fWidth,
983 glTexDesc.fHeight,
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000984 glTexDesc.fTextureID,
985 &glRTDesc)) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000986 GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000987 return return_null_texture();
988 }
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000989 tex = SkNEW_ARGS(GrGLTexture, (this, glTexDesc, glRTDesc));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000990 } else {
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000991 tex = SkNEW_ARGS(GrGLTexture, (this, glTexDesc));
reed@google.comac10a2d2010-12-22 21:39:39 +0000992 }
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000993 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
reed@google.comac10a2d2010-12-22 21:39:39 +0000994#ifdef TRACE_TEXTURE_CREATION
bsalomon@google.com64c4fe42011-11-05 14:51:01 +0000995 GrPrintf("--- new texture [%d] size=(%d %d) config=%d\n",
996 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig);
reed@google.comac10a2d2010-12-22 21:39:39 +0000997#endif
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +0000998 return tex;
999}
1000
1001namespace {
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001002
1003const GrGLuint kUnknownBitCount = GrGLStencilBuffer::kUnknownBitCount;
1004
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001005void inline get_stencil_rb_sizes(const GrGLInterface* gl,
rmistry@google.comfbfcd562012-08-23 18:09:54 +00001006 GrGLuint rb,
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001007 GrGLStencilBuffer::Format* format) {
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001008 // we shouldn't ever know one size and not the other
1009 GrAssert((kUnknownBitCount == format->fStencilBits) ==
1010 (kUnknownBitCount == format->fTotalBits));
1011 if (kUnknownBitCount == format->fStencilBits) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001012 GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001013 GR_GL_RENDERBUFFER_STENCIL_SIZE,
1014 (GrGLint*)&format->fStencilBits);
1015 if (format->fPacked) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001016 GR_GL_GetRenderbufferParameteriv(gl, GR_GL_RENDERBUFFER,
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001017 GR_GL_RENDERBUFFER_DEPTH_SIZE,
1018 (GrGLint*)&format->fTotalBits);
1019 format->fTotalBits += format->fStencilBits;
1020 } else {
1021 format->fTotalBits = format->fStencilBits;
1022 }
1023 }
1024}
1025}
1026
1027bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
1028 int width, int height) {
1029
1030 // All internally created RTs are also textures. We don't create
robertphillips@google.com1f47f4f2012-08-16 14:49:16 +00001031 // SBs for a client's standalone RT (that is a RT that isn't also a texture).
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001032 GrAssert(rt->asTexture());
bsalomon@google.com99621082011-11-15 16:47:16 +00001033 GrAssert(width >= rt->width());
1034 GrAssert(height >= rt->height());
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001035
1036 int samples = rt->numSamples();
1037 GrGLuint sbID;
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001038 GL_CALL(GenRenderbuffers(1, &sbID));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001039 if (!sbID) {
1040 return false;
1041 }
1042
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001043 int stencilFmtCnt = this->glCaps().stencilFormats().count();
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001044 for (int i = 0; i < stencilFmtCnt; ++i) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001045 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbID));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001046 // we start with the last stencil format that succeeded in hopes
1047 // that we won't go through this loop more than once after the
1048 // first (painful) stencil creation.
1049 int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001050 const GrGLCaps::StencilFormat& sFmt =
1051 this->glCaps().stencilFormats()[sIdx];
bsalomon@google.com4f3c2532012-01-19 16:16:52 +00001052 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
bsalomon@google.com558a75b2011-08-08 17:01:14 +00001053 // we do this "if" so that we don't call the multisample
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001054 // version on a GL that doesn't have an MSAA extension.
bsalomon@google.comc9668ec2012-04-11 18:16:41 +00001055 bool created;
1056 if (samples > 0) {
robertphillips@google.com6177e692013-02-28 20:16:25 +00001057 created = renderbuffer_storage_msaa(fGLContext,
bsalomon@google.comc9668ec2012-04-11 18:16:41 +00001058 samples,
1059 sFmt.fInternalFormat,
1060 width, height);
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001061 } else {
bsalomon@google.com4f3c2532012-01-19 16:16:52 +00001062 GL_ALLOC_CALL(this->glInterface(),
1063 RenderbufferStorage(GR_GL_RENDERBUFFER,
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001064 sFmt.fInternalFormat,
bsalomon@google.com4f3c2532012-01-19 16:16:52 +00001065 width, height));
bsalomon@google.comc9668ec2012-04-11 18:16:41 +00001066 created =
1067 (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(this->glInterface()));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001068 }
bsalomon@google.comc9668ec2012-04-11 18:16:41 +00001069 if (created) {
1070 // After sized formats we attempt an unsized format and take
1071 // whatever sizes GL gives us. In that case we query for the size.
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001072 GrGLStencilBuffer::Format format = sFmt;
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001073 get_stencil_rb_sizes(this->glInterface(), sbID, &format);
bsalomon@google.com72830222013-01-23 20:25:22 +00001074 static const bool kIsWrapped = false;
robertphillips@google.comf2e93fc2012-09-05 19:44:18 +00001075 SkAutoTUnref<GrStencilBuffer> sb(SkNEW_ARGS(GrGLStencilBuffer,
bsalomon@google.com72830222013-01-23 20:25:22 +00001076 (this, kIsWrapped, sbID, width, height,
robertphillips@google.comf2e93fc2012-09-05 19:44:18 +00001077 samples, format)));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001078 if (this->attachStencilBufferToRenderTarget(sb, rt)) {
1079 fLastSuccessfulStencilFmtIdx = sIdx;
robertphillips@google.com9fbcad02012-09-09 14:44:15 +00001080 sb->transferToCache();
bsalomon@google.com558a75b2011-08-08 17:01:14 +00001081 rt->setStencilBuffer(sb);
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001082 return true;
1083 }
1084 sb->abandon(); // otherwise we lose sbID
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001085 }
1086 }
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001087 GL_CALL(DeleteRenderbuffers(1, &sbID));
bsalomon@google.com558a75b2011-08-08 17:01:14 +00001088 return false;
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001089}
1090
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001091bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTarget* rt) {
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001092 GrGLRenderTarget* glrt = (GrGLRenderTarget*) rt;
1093
1094 GrGLuint fbo = glrt->renderFBOID();
1095
1096 if (NULL == sb) {
1097 if (NULL != rt->getStencilBuffer()) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001098 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001099 GR_GL_STENCIL_ATTACHMENT,
1100 GR_GL_RENDERBUFFER, 0));
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001101 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001102 GR_GL_DEPTH_ATTACHMENT,
1103 GR_GL_RENDERBUFFER, 0));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001104#if GR_DEBUG
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +00001105 GrGLenum status;
1106 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001107 GrAssert(GR_GL_FRAMEBUFFER_COMPLETE == status);
1108#endif
1109 }
1110 return true;
1111 } else {
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001112 GrGLStencilBuffer* glsb = static_cast<GrGLStencilBuffer*>(sb);
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001113 GrGLuint rb = glsb->renderbufferID();
1114
bsalomon@google.comc811ea32012-05-21 15:33:09 +00001115 fHWBoundRenderTarget = NULL;
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001116 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo));
1117 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001118 GR_GL_STENCIL_ATTACHMENT,
1119 GR_GL_RENDERBUFFER, rb));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001120 if (glsb->format().fPacked) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001121 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001122 GR_GL_DEPTH_ATTACHMENT,
1123 GR_GL_RENDERBUFFER, rb));
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001124 } else {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001125 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001126 GR_GL_DEPTH_ATTACHMENT,
1127 GR_GL_RENDERBUFFER, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001128 }
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001129
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +00001130 GrGLenum status;
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001131 if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(), glsb->format())) {
bsalomon@google.com4bcb0c62012-02-07 16:06:47 +00001132 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1133 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001134 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
bsalomon@google.com4bcb0c62012-02-07 16:06:47 +00001135 GR_GL_STENCIL_ATTACHMENT,
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001136 GR_GL_RENDERBUFFER, 0));
bsalomon@google.com4bcb0c62012-02-07 16:06:47 +00001137 if (glsb->format().fPacked) {
1138 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1139 GR_GL_DEPTH_ATTACHMENT,
1140 GR_GL_RENDERBUFFER, 0));
1141 }
1142 return false;
1143 } else {
bsalomon@google.combcce8922013-03-25 15:38:39 +00001144 fGLContext.info().caps()->markColorConfigAndStencilFormatAsVerified(
bsalomon@google.com4bcb0c62012-02-07 16:06:47 +00001145 rt->config(),
1146 glsb->format());
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001147 }
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001148 }
bsalomon@google.com4bcb0c62012-02-07 16:06:47 +00001149 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001150 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001151}
1152
bsalomon@google.com71f341a2011-08-01 13:36:00 +00001153////////////////////////////////////////////////////////////////////////////////
1154
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001155GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
bsalomon@google.come49ad452013-02-20 19:33:20 +00001156 GrGLVertexBuffer::Desc desc;
1157 desc.fDynamic = dynamic;
1158 desc.fSizeInBytes = size;
1159 desc.fIsWrapped = false;
1160
bsalomon@google.com96966a52013-02-21 16:34:21 +00001161 if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && desc.fDynamic) {
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +00001162 desc.fID = 0;
bsalomon@google.come49ad452013-02-20 19:33:20 +00001163 GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer, (this, desc));
reed@google.comac10a2d2010-12-22 21:39:39 +00001164 return vertexBuffer;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +00001165 } else {
1166 GL_CALL(GenBuffers(1, &desc.fID));
1167 if (desc.fID) {
bsalomon@google.com6918d482013-03-07 19:09:11 +00001168 fHWGeometryState.setVertexBufferID(this, desc.fID);
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +00001169 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1170 // make sure driver can allocate memory for this buffer
1171 GL_ALLOC_CALL(this->glInterface(),
1172 BufferData(GR_GL_ARRAY_BUFFER,
1173 desc.fSizeInBytes,
1174 NULL, // data ptr
1175 desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1176 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
1177 GL_CALL(DeleteBuffers(1, &desc.fID));
bsalomon@google.com6918d482013-03-07 19:09:11 +00001178 this->notifyVertexBufferDelete(desc.fID);
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +00001179 return NULL;
1180 }
1181 GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer, (this, desc));
1182 return vertexBuffer;
1183 }
1184 return NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001185 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001186}
1187
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001188GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
bsalomon@google.come49ad452013-02-20 19:33:20 +00001189 GrGLIndexBuffer::Desc desc;
1190 desc.fDynamic = dynamic;
1191 desc.fSizeInBytes = size;
1192 desc.fIsWrapped = false;
1193
bsalomon@google.com96966a52013-02-21 16:34:21 +00001194 if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && desc.fDynamic) {
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +00001195 desc.fID = 0;
bsalomon@google.come49ad452013-02-20 19:33:20 +00001196 GrIndexBuffer* indexBuffer = SkNEW_ARGS(GrGLIndexBuffer, (this, desc));
reed@google.comac10a2d2010-12-22 21:39:39 +00001197 return indexBuffer;
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +00001198 } else {
1199 GL_CALL(GenBuffers(1, &desc.fID));
1200 if (desc.fID) {
bsalomon@google.com6918d482013-03-07 19:09:11 +00001201 fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, desc.fID);
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +00001202 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
1203 // make sure driver can allocate memory for this buffer
1204 GL_ALLOC_CALL(this->glInterface(),
1205 BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
1206 desc.fSizeInBytes,
1207 NULL, // data ptr
1208 desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1209 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
1210 GL_CALL(DeleteBuffers(1, &desc.fID));
bsalomon@google.com6918d482013-03-07 19:09:11 +00001211 this->notifyIndexBufferDelete(desc.fID);
bsalomon@google.comee3bc3b2013-02-21 14:33:46 +00001212 return NULL;
1213 }
1214 GrIndexBuffer* indexBuffer = SkNEW_ARGS(GrGLIndexBuffer, (this, desc));
1215 return indexBuffer;
1216 }
1217 return NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001218 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001219}
1220
bsalomon@google.com64aef2b2012-06-11 15:36:13 +00001221GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) {
bsalomon@google.combcce8922013-03-25 15:38:39 +00001222 GrAssert(this->caps()->pathStencilingSupport());
tomhudson@google.comc377baf2012-07-09 20:17:56 +00001223 return SkNEW_ARGS(GrGLPath, (this, inPath));
bsalomon@google.com64aef2b2012-06-11 15:36:13 +00001224}
1225
bsalomon@google.coma3201942012-06-21 19:58:20 +00001226void GrGpuGL::flushScissor() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001227 const GrDrawState& drawState = this->getDrawState();
1228 const GrGLRenderTarget* rt =
1229 static_cast<const GrGLRenderTarget*>(drawState.getRenderTarget());
1230
1231 GrAssert(NULL != rt);
1232 const GrGLIRect& vp = rt->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001233
bsalomon@google.coma3201942012-06-21 19:58:20 +00001234 if (fScissorState.fEnabled) {
1235 GrGLIRect scissor;
1236 scissor.setRelativeTo(vp,
1237 fScissorState.fRect.fLeft,
1238 fScissorState.fRect.fTop,
1239 fScissorState.fRect.width(),
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001240 fScissorState.fRect.height(),
1241 rt->origin());
bsalomon@google.coma3201942012-06-21 19:58:20 +00001242 // if the scissor fully contains the viewport then we fall through and
1243 // disable the scissor test.
1244 if (!scissor.contains(vp)) {
1245 if (fHWScissorSettings.fRect != scissor) {
1246 scissor.pushToGLScissor(this->glInterface());
1247 fHWScissorSettings.fRect = scissor;
1248 }
1249 if (kYes_TriState != fHWScissorSettings.fEnabled) {
1250 GL_CALL(Enable(GR_GL_SCISSOR_TEST));
1251 fHWScissorSettings.fEnabled = kYes_TriState;
1252 }
1253 return;
1254 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001255 }
bsalomon@google.coma3201942012-06-21 19:58:20 +00001256 if (kNo_TriState != fHWScissorSettings.fEnabled) {
robertphillips@google.com730ebe52012-04-16 16:33:13 +00001257 GL_CALL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.coma3201942012-06-21 19:58:20 +00001258 fHWScissorSettings.fEnabled = kNo_TriState;
1259 return;
reed@google.comac10a2d2010-12-22 21:39:39 +00001260 }
1261}
1262
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001263void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001264 const GrDrawState& drawState = this->getDrawState();
1265 const GrRenderTarget* rt = drawState.getRenderTarget();
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +00001266 // parent class should never let us get here with no RT
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001267 GrAssert(NULL != rt);
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +00001268
bsalomon@google.com74b98712011-11-11 19:46:16 +00001269 GrIRect clippedRect;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001270 if (NULL != rect) {
1271 // flushScissor expects rect to be clipped to the target.
bsalomon@google.com74b98712011-11-11 19:46:16 +00001272 clippedRect = *rect;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001273 GrIRect rtRect = SkIRect::MakeWH(rt->width(), rt->height());
bsalomon@google.com74b98712011-11-11 19:46:16 +00001274 if (clippedRect.intersect(rtRect)) {
1275 rect = &clippedRect;
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001276 } else {
1277 return;
1278 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001279 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001280 this->flushRenderTarget(rect);
bsalomon@google.coma3201942012-06-21 19:58:20 +00001281 GrAutoTRestore<ScissorState> asr(&fScissorState);
1282 fScissorState.fEnabled = (NULL != rect);
1283 if (fScissorState.fEnabled) {
1284 fScissorState.fRect = *rect;
1285 }
1286 this->flushScissor();
bsalomon@google.com74b98712011-11-11 19:46:16 +00001287
1288 GrGLfloat r, g, b, a;
1289 static const GrGLfloat scale255 = 1.f / 255.f;
1290 a = GrColorUnpackA(color) * scale255;
1291 GrGLfloat scaleRGB = scale255;
bsalomon@google.com74b98712011-11-11 19:46:16 +00001292 r = GrColorUnpackR(color) * scaleRGB;
1293 g = GrColorUnpackG(color) * scaleRGB;
1294 b = GrColorUnpackB(color) * scaleRGB;
1295
1296 GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001297 fHWWriteToColor = kYes_TriState;
bsalomon@google.com74b98712011-11-11 19:46:16 +00001298 GL_CALL(ClearColor(r, g, b, a));
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001299 GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001300}
1301
bsalomon@google.comedc177d2011-08-05 15:46:40 +00001302void GrGpuGL::clearStencil() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001303 if (NULL == this->getDrawState().getRenderTarget()) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001304 return;
1305 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +00001306
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001307 this->flushRenderTarget(&GrIRect::EmptyIRect());
1308
bsalomon@google.coma3201942012-06-21 19:58:20 +00001309 GrAutoTRestore<ScissorState> asr(&fScissorState);
1310 fScissorState.fEnabled = false;
1311 this->flushScissor();
robertphillips@google.com730ebe52012-04-16 16:33:13 +00001312
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001313 GL_CALL(StencilMask(0xffffffff));
1314 GL_CALL(ClearStencil(0));
1315 GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.com457b8a32012-05-21 21:19:58 +00001316 fHWStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001317}
1318
bsalomon@google.comab3dee52011-08-29 15:18:41 +00001319void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001320 const GrDrawState& drawState = this->getDrawState();
1321 const GrRenderTarget* rt = drawState.getRenderTarget();
1322 GrAssert(NULL != rt);
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001323
1324 // this should only be called internally when we know we have a
1325 // stencil buffer.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001326 GrAssert(NULL != rt->getStencilBuffer());
1327 GrGLint stencilBitCount = rt->getStencilBuffer()->bits();
bsalomon@google.comab3dee52011-08-29 15:18:41 +00001328#if 0
reed@google.comac10a2d2010-12-22 21:39:39 +00001329 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001330 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001331#else
1332 // we could just clear the clip bit but when we go through
bsalomon@google.com81c3f8d2011-08-03 15:18:33 +00001333 // ANGLE a partial stencil mask will cause clears to be
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001334 // turned into draws. Our contract on GrDrawTarget says that
1335 // changing the clip between stencil passes may or may not
1336 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001337 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001338#endif
bsalomon@google.comab3dee52011-08-29 15:18:41 +00001339 GrGLint value;
1340 if (insideClip) {
1341 value = (1 << (stencilBitCount - 1));
1342 } else {
1343 value = 0;
1344 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001345 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.coma3201942012-06-21 19:58:20 +00001346
1347 GrAutoTRestore<ScissorState> asr(&fScissorState);
1348 fScissorState.fEnabled = true;
1349 fScissorState.fRect = rect;
1350 this->flushScissor();
1351
caryclark@google.comcf6285b2012-06-06 12:09:01 +00001352 GL_CALL(StencilMask((uint32_t) clipStencilMask));
bsalomon@google.comab3dee52011-08-29 15:18:41 +00001353 GL_CALL(ClearStencil(value));
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001354 GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.com457b8a32012-05-21 21:19:58 +00001355 fHWStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001356}
1357
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001358void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001359 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001360}
1361
bsalomon@google.comc4364992011-11-07 15:54:49 +00001362bool GrGpuGL::readPixelsWillPayForYFlip(GrRenderTarget* renderTarget,
1363 int left, int top,
1364 int width, int height,
1365 GrPixelConfig config,
bsalomon@google.com56d11e02011-11-30 19:59:08 +00001366 size_t rowBytes) const {
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001367 // If this rendertarget is aready TopLeft, we don't need to flip.
1368 if (kTopLeft_GrSurfaceOrigin == renderTarget->origin()) {
1369 return false;
1370 }
1371
bsalomon@google.com56d11e02011-11-30 19:59:08 +00001372 // if GL can do the flip then we'll never pay for it.
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001373 if (this->glCaps().packFlipYSupport()) {
bsalomon@google.com56d11e02011-11-30 19:59:08 +00001374 return false;
1375 }
1376
1377 // If we have to do memcpy to handle non-trim rowBytes then we
bsalomon@google.com7107fa72011-11-10 14:54:14 +00001378 // get the flip for free. Otherwise it costs.
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001379 if (this->glCaps().packRowLengthSupport()) {
bsalomon@google.coma85449d2011-11-19 02:36:05 +00001380 return true;
1381 }
1382 // If we have to do memcpys to handle rowBytes then y-flip is free
1383 // Note the rowBytes might be tight to the passed in data, but if data
1384 // gets clipped in x to the target the rowBytes will no longer be tight.
1385 if (left >= 0 && (left + width) < renderTarget->width()) {
1386 return 0 == rowBytes ||
1387 GrBytesPerPixel(config) * width == rowBytes;
1388 } else {
1389 return false;
1390 }
bsalomon@google.comc4364992011-11-07 15:54:49 +00001391}
1392
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001393bool GrGpuGL::onReadPixels(GrRenderTarget* target,
bsalomon@google.comc6980972011-11-02 19:57:21 +00001394 int left, int top,
1395 int width, int height,
bsalomon@google.comc4364992011-11-07 15:54:49 +00001396 GrPixelConfig config,
1397 void* buffer,
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001398 size_t rowBytes) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001399 GrGLenum format;
1400 GrGLenum type;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001401 bool flipY = kBottomLeft_GrSurfaceOrigin == target->origin();
bsalomon@google.com280e99f2012-01-05 16:17:38 +00001402 if (!this->configToGLFormats(config, false, NULL, &format, &type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001403 return false;
bsalomon@google.comc6980972011-11-02 19:57:21 +00001404 }
bsalomon@google.coma85449d2011-11-19 02:36:05 +00001405 size_t bpp = GrBytesPerPixel(config);
1406 if (!adjust_pixel_ops_params(target->width(), target->height(), bpp,
1407 &left, &top, &width, &height,
1408 const_cast<const void**>(&buffer),
1409 &rowBytes)) {
1410 return false;
1411 }
bsalomon@google.comc4364992011-11-07 15:54:49 +00001412
bsalomon@google.comc6980972011-11-02 19:57:21 +00001413 // resolve the render target if necessary
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001414 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001415 GrDrawState::AutoRenderTargetRestore artr;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001416 switch (tgt->getResolveType()) {
1417 case GrGLRenderTarget::kCantResolve_ResolveType:
1418 return false;
1419 case GrGLRenderTarget::kAutoResolves_ResolveType:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001420 artr.set(this->drawState(), target);
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001421 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001422 break;
1423 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com75f9f252012-01-31 13:35:56 +00001424 this->onResolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001425 // we don't track the state of the READ FBO ID.
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001426 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
1427 tgt->textureFBOID()));
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001428 break;
1429 default:
1430 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001431 }
1432
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001433 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001434
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001435 // the read rect is viewport-relative
1436 GrGLIRect readRect;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001437 readRect.setRelativeTo(glvp, left, top, width, height, target->origin());
rmistry@google.comfbfcd562012-08-23 18:09:54 +00001438
bsalomon@google.coma85449d2011-11-19 02:36:05 +00001439 size_t tightRowBytes = bpp * width;
bsalomon@google.comc6980972011-11-02 19:57:21 +00001440 if (0 == rowBytes) {
1441 rowBytes = tightRowBytes;
1442 }
1443 size_t readDstRowBytes = tightRowBytes;
1444 void* readDst = buffer;
rmistry@google.comfbfcd562012-08-23 18:09:54 +00001445
bsalomon@google.comc6980972011-11-02 19:57:21 +00001446 // determine if GL can read using the passed rowBytes or if we need
1447 // a scratch buffer.
1448 SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
1449 if (rowBytes != tightRowBytes) {
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001450 if (this->glCaps().packRowLengthSupport()) {
bsalomon@google.comc6980972011-11-02 19:57:21 +00001451 GrAssert(!(rowBytes % sizeof(GrColor)));
1452 GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, rowBytes / sizeof(GrColor)));
1453 readDstRowBytes = rowBytes;
1454 } else {
1455 scratch.reset(tightRowBytes * height);
1456 readDst = scratch.get();
1457 }
1458 }
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001459 if (flipY && this->glCaps().packFlipYSupport()) {
bsalomon@google.com56d11e02011-11-30 19:59:08 +00001460 GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 1));
1461 }
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001462 GL_CALL(ReadPixels(readRect.fLeft, readRect.fBottom,
1463 readRect.fWidth, readRect.fHeight,
bsalomon@google.comc6980972011-11-02 19:57:21 +00001464 format, type, readDst));
1465 if (readDstRowBytes != tightRowBytes) {
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001466 GrAssert(this->glCaps().packRowLengthSupport());
bsalomon@google.comc6980972011-11-02 19:57:21 +00001467 GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
1468 }
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001469 if (flipY && this->glCaps().packFlipYSupport()) {
bsalomon@google.com56d11e02011-11-30 19:59:08 +00001470 GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 0));
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001471 flipY = false;
bsalomon@google.com56d11e02011-11-30 19:59:08 +00001472 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001473
1474 // now reverse the order of the rows, since GL's are bottom-to-top, but our
bsalomon@google.comc6980972011-11-02 19:57:21 +00001475 // API presents top-to-bottom. We must preserve the padding contents. Note
1476 // that the above readPixels did not overwrite the padding.
1477 if (readDst == buffer) {
1478 GrAssert(rowBytes == readDstRowBytes);
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001479 if (flipY) {
bsalomon@google.comc4364992011-11-07 15:54:49 +00001480 scratch.reset(tightRowBytes);
1481 void* tmpRow = scratch.get();
1482 // flip y in-place by rows
1483 const int halfY = height >> 1;
1484 char* top = reinterpret_cast<char*>(buffer);
1485 char* bottom = top + (height - 1) * rowBytes;
1486 for (int y = 0; y < halfY; y++) {
1487 memcpy(tmpRow, top, tightRowBytes);
1488 memcpy(top, bottom, tightRowBytes);
1489 memcpy(bottom, tmpRow, tightRowBytes);
1490 top += rowBytes;
1491 bottom -= rowBytes;
1492 }
bsalomon@google.comc6980972011-11-02 19:57:21 +00001493 }
1494 } else {
bsalomon@google.comc4364992011-11-07 15:54:49 +00001495 GrAssert(readDst != buffer); GrAssert(rowBytes != tightRowBytes);
bsalomon@google.comc6980972011-11-02 19:57:21 +00001496 // copy from readDst to buffer while flipping y
caryclark@google.comcf6285b2012-06-06 12:09:01 +00001497 // const int halfY = height >> 1;
bsalomon@google.comc6980972011-11-02 19:57:21 +00001498 const char* src = reinterpret_cast<const char*>(readDst);
bsalomon@google.comc4364992011-11-07 15:54:49 +00001499 char* dst = reinterpret_cast<char*>(buffer);
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001500 if (flipY) {
bsalomon@google.comc4364992011-11-07 15:54:49 +00001501 dst += (height-1) * rowBytes;
1502 }
bsalomon@google.comc6980972011-11-02 19:57:21 +00001503 for (int y = 0; y < height; y++) {
1504 memcpy(dst, src, tightRowBytes);
1505 src += readDstRowBytes;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +00001506 if (!flipY) {
bsalomon@google.comc4364992011-11-07 15:54:49 +00001507 dst += rowBytes;
1508 } else {
1509 dst -= rowBytes;
1510 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001511 }
1512 }
1513 return true;
1514}
1515
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001516void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001517
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001518 GrGLRenderTarget* rt =
1519 static_cast<GrGLRenderTarget*>(this->drawState()->getRenderTarget());
1520 GrAssert(NULL != rt);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001521
bsalomon@google.comc811ea32012-05-21 15:33:09 +00001522 if (fHWBoundRenderTarget != rt) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001523 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001524 #if GR_DEBUG
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +00001525 GrGLenum status;
1526 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001527 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001528 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001529 }
1530 #endif
bsalomon@google.comc811ea32012-05-21 15:33:09 +00001531 fHWBoundRenderTarget = rt;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001532 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.coma3201942012-06-21 19:58:20 +00001533 if (fHWViewport != vp) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001534 vp.pushToGLViewport(this->glInterface());
bsalomon@google.coma3201942012-06-21 19:58:20 +00001535 fHWViewport = vp;
reed@google.comac10a2d2010-12-22 21:39:39 +00001536 }
1537 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001538 if (NULL == bound || !bound->isEmpty()) {
1539 rt->flagAsNeedingResolve(bound);
1540 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001541}
1542
twiz@google.com0f31ca72011-03-18 17:38:11 +00001543GrGLenum gPrimitiveType2GLMode[] = {
1544 GR_GL_TRIANGLES,
1545 GR_GL_TRIANGLE_STRIP,
1546 GR_GL_TRIANGLE_FAN,
1547 GR_GL_POINTS,
1548 GR_GL_LINES,
1549 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001550};
1551
bsalomon@google.comd302f142011-03-03 13:54:13 +00001552#define SWAP_PER_DRAW 0
1553
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001554#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001555 #if GR_MAC_BUILD
1556 #include <AGL/agl.h>
1557 #elif GR_WIN32_BUILD
bsalomon@google.comce7357d2012-06-25 17:49:25 +00001558 #include <gl/GL.h>
bsalomon@google.comd302f142011-03-03 13:54:13 +00001559 void SwapBuf() {
1560 DWORD procID = GetCurrentProcessId();
1561 HWND hwnd = GetTopWindow(GetDesktopWindow());
1562 while(hwnd) {
1563 DWORD wndProcID = 0;
1564 GetWindowThreadProcessId(hwnd, &wndProcID);
1565 if(wndProcID == procID) {
1566 SwapBuffers(GetDC(hwnd));
1567 }
1568 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1569 }
1570 }
1571 #endif
1572#endif
1573
bsalomon@google.com74749cd2013-01-30 16:12:41 +00001574void GrGpuGL::onGpuDraw(const DrawInfo& info) {
bsalomon@google.com880b8fc2013-02-19 20:17:28 +00001575 size_t indexOffsetInBytes;
1576 this->setupGeometry(info, &indexOffsetInBytes);
reed@google.comac10a2d2010-12-22 21:39:39 +00001577
bsalomon@google.com74749cd2013-01-30 16:12:41 +00001578 GrAssert((size_t)info.primitiveType() < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001579
bsalomon@google.com74749cd2013-01-30 16:12:41 +00001580 if (info.isIndexed()) {
bsalomon@google.com880b8fc2013-02-19 20:17:28 +00001581 GrGLvoid* indices =
1582 reinterpret_cast<GrGLvoid*>(indexOffsetInBytes + sizeof(uint16_t) * info.startIndex());
bsalomon@google.com74749cd2013-01-30 16:12:41 +00001583 // info.startVertex() was accounted for by setupGeometry.
1584 GL_CALL(DrawElements(gPrimitiveType2GLMode[info.primitiveType()],
1585 info.indexCount(),
1586 GR_GL_UNSIGNED_SHORT,
1587 indices));
1588 } else {
1589 // Pass 0 for parameter first. We have to adjust glVertexAttribPointer() to account for
1590 // startVertex in the DrawElements case. So we always rely on setupGeometry to have
1591 // accounted for startVertex.
1592 GL_CALL(DrawArrays(gPrimitiveType2GLMode[info.primitiveType()], 0, info.vertexCount()));
1593 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001594#if SWAP_PER_DRAW
1595 glFlush();
1596 #if GR_MAC_BUILD
1597 aglSwapBuffers(aglGetCurrentContext());
1598 int set_a_break_pt_here = 9;
1599 aglSwapBuffers(aglGetCurrentContext());
1600 #elif GR_WIN32_BUILD
1601 SwapBuf();
1602 int set_a_break_pt_here = 9;
1603 SwapBuf();
1604 #endif
1605#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001606}
1607
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001608namespace {
bsalomon@google.com100abf42012-09-05 17:40:04 +00001609
1610static const uint16_t kOnes16 = static_cast<uint16_t>(~0);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001611const GrStencilSettings& winding_nv_path_stencil_settings() {
1612 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
1613 kIncClamp_StencilOp,
1614 kIncClamp_StencilOp,
1615 kAlwaysIfInClip_StencilFunc,
bsalomon@google.com100abf42012-09-05 17:40:04 +00001616 kOnes16, kOnes16, kOnes16);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001617 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
1618}
1619const GrStencilSettings& even_odd_nv_path_stencil_settings() {
1620 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
1621 kInvert_StencilOp,
1622 kInvert_StencilOp,
1623 kAlwaysIfInClip_StencilFunc,
bsalomon@google.com100abf42012-09-05 17:40:04 +00001624 kOnes16, kOnes16, kOnes16);
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001625 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
1626}
1627}
1628
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001629void GrGpuGL::setStencilPathSettings(const GrPath&,
sugoi@google.com12b4e272012-12-06 20:13:11 +00001630 SkPath::FillType fill,
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001631 GrStencilSettings* settings) {
1632 switch (fill) {
sugoi@google.com12b4e272012-12-06 20:13:11 +00001633 case SkPath::kEvenOdd_FillType:
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001634 *settings = even_odd_nv_path_stencil_settings();
1635 return;
sugoi@google.com12b4e272012-12-06 20:13:11 +00001636 case SkPath::kWinding_FillType:
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001637 *settings = winding_nv_path_stencil_settings();
1638 return;
1639 default:
1640 GrCrash("Unexpected path fill.");
1641 }
1642}
1643
sugoi@google.com12b4e272012-12-06 20:13:11 +00001644void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) {
bsalomon@google.combcce8922013-03-25 15:38:39 +00001645 GrAssert(this->caps()->pathStencilingSupport());
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001646
1647 GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
1648 GrDrawState* drawState = this->drawState();
1649 GrAssert(NULL != drawState->getRenderTarget());
1650 if (NULL == drawState->getRenderTarget()->getStencilBuffer()) {
1651 return;
1652 }
1653
1654 // Decide how to manipulate the stencil buffer based on the fill rule.
1655 // Also, assert that the stencil settings we set in setStencilPathSettings
1656 // are present.
1657 GrAssert(!fStencilSettings.isTwoSided());
1658 GrGLenum fillMode;
1659 switch (fill) {
sugoi@google.com12b4e272012-12-06 20:13:11 +00001660 case SkPath::kWinding_FillType:
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001661 fillMode = GR_GL_COUNT_UP;
1662 GrAssert(kIncClamp_StencilOp ==
1663 fStencilSettings.passOp(GrStencilSettings::kFront_Face));
1664 GrAssert(kIncClamp_StencilOp ==
1665 fStencilSettings.failOp(GrStencilSettings::kFront_Face));
1666 break;
sugoi@google.com12b4e272012-12-06 20:13:11 +00001667 case SkPath::kEvenOdd_FillType:
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001668 fillMode = GR_GL_INVERT;
1669 GrAssert(kInvert_StencilOp ==
1670 fStencilSettings.passOp(GrStencilSettings::kFront_Face));
1671 GrAssert(kInvert_StencilOp ==
1672 fStencilSettings.failOp(GrStencilSettings::kFront_Face));
1673 break;
1674 default:
1675 // Only the above two fill rules are allowed.
1676 GrCrash("Unexpected path fill.");
bsalomon@google.com548a4332012-07-11 19:45:22 +00001677 return; // suppress unused var warning.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001678 }
1679 GrGLint writeMask = fStencilSettings.writeMask(GrStencilSettings::kFront_Face);
1680 GL_CALL(StencilFillPath(id, fillMode, writeMask));
bsalomon@google.com64aef2b2012-06-11 15:36:13 +00001681}
1682
bsalomon@google.com75f9f252012-01-31 13:35:56 +00001683void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
bsalomon@google.com75f9f252012-01-31 13:35:56 +00001684 GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001685 if (rt->needsResolve()) {
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001686 // The IMG extension automatically resolves the texture when it is read.
1687 if (GrGLCaps::kImaginationES_MSFBOType != this->glCaps().msFBOType()) {
1688 GrAssert(GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType());
1689 GrAssert(rt->textureFBOID() != rt->renderFBOID());
1690 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID()));
1691 GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID()));
1692 // make sure we go through flushRenderTarget() since we've modified
1693 // the bound DRAW FBO ID.
1694 fHWBoundRenderTarget = NULL;
1695 const GrGLIRect& vp = rt->getViewport();
1696 const GrIRect dirtyRect = rt->getResolveRect();
1697 GrGLIRect r;
1698 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1699 dirtyRect.width(), dirtyRect.height(), target->origin());
reed@google.comac10a2d2010-12-22 21:39:39 +00001700
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001701 GrAutoTRestore<ScissorState> asr;
1702 if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) {
1703 // Apple's extension uses the scissor as the blit bounds.
bsalomon@google.coma3201942012-06-21 19:58:20 +00001704 asr.reset(&fScissorState);
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001705 fScissorState.fEnabled = true;
1706 fScissorState.fRect = dirtyRect;
bsalomon@google.coma3201942012-06-21 19:58:20 +00001707 this->flushScissor();
bsalomon@google.comf3a60c02013-03-19 19:06:09 +00001708 GL_CALL(ResolveMultisampleFramebuffer());
1709 } else {
1710 if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) {
1711 // this respects the scissor during the blit, so disable it.
1712 GrAssert(GrGLCaps::kDesktopEXT_MSFBOType == this->glCaps().msFBOType());
1713 asr.reset(&fScissorState);
1714 fScissorState.fEnabled = false;
1715 this->flushScissor();
1716 }
1717 int right = r.fLeft + r.fWidth;
1718 int top = r.fBottom + r.fHeight;
1719 GL_CALL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1720 r.fLeft, r.fBottom, right, top,
1721 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001722 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001723 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001724 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001725 }
1726}
1727
bsalomon@google.com411dad02012-06-05 20:24:20 +00001728namespace {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001729
bsalomon@google.com411dad02012-06-05 20:24:20 +00001730GrGLenum gr_to_gl_stencil_func(GrStencilFunc basicFunc) {
1731 static const GrGLenum gTable[] = {
1732 GR_GL_ALWAYS, // kAlways_StencilFunc
1733 GR_GL_NEVER, // kNever_StencilFunc
1734 GR_GL_GREATER, // kGreater_StencilFunc
1735 GR_GL_GEQUAL, // kGEqual_StencilFunc
1736 GR_GL_LESS, // kLess_StencilFunc
1737 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1738 GR_GL_EQUAL, // kEqual_StencilFunc,
1739 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
1740 };
1741 GR_STATIC_ASSERT(GR_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
1742 GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1743 GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1744 GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1745 GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1746 GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1747 GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1748 GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1749 GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1750 GrAssert((unsigned) basicFunc < kBasicStencilFuncCount);
1751
1752 return gTable[basicFunc];
1753}
1754
1755GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
1756 static const GrGLenum gTable[] = {
1757 GR_GL_KEEP, // kKeep_StencilOp
1758 GR_GL_REPLACE, // kReplace_StencilOp
1759 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1760 GR_GL_INCR, // kIncClamp_StencilOp
1761 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1762 GR_GL_DECR, // kDecClamp_StencilOp
1763 GR_GL_ZERO, // kZero_StencilOp
1764 GR_GL_INVERT, // kInvert_StencilOp
1765 };
1766 GR_STATIC_ASSERT(GR_ARRAY_COUNT(gTable) == kStencilOpCount);
1767 GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1768 GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1769 GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1770 GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1771 GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1772 GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1773 GR_STATIC_ASSERT(6 == kZero_StencilOp);
1774 GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1775 GrAssert((unsigned) op < kStencilOpCount);
1776 return gTable[op];
1777}
1778
1779void set_gl_stencil(const GrGLInterface* gl,
bsalomon@google.coma3201942012-06-21 19:58:20 +00001780 const GrStencilSettings& settings,
bsalomon@google.com411dad02012-06-05 20:24:20 +00001781 GrGLenum glFace,
bsalomon@google.coma3201942012-06-21 19:58:20 +00001782 GrStencilSettings::Face grFace) {
1783 GrGLenum glFunc = gr_to_gl_stencil_func(settings.func(grFace));
1784 GrGLenum glFailOp = gr_to_gl_stencil_op(settings.failOp(grFace));
1785 GrGLenum glPassOp = gr_to_gl_stencil_op(settings.passOp(grFace));
1786
1787 GrGLint ref = settings.funcRef(grFace);
1788 GrGLint mask = settings.funcMask(grFace);
1789 GrGLint writeMask = settings.writeMask(grFace);
bsalomon@google.com411dad02012-06-05 20:24:20 +00001790
1791 if (GR_GL_FRONT_AND_BACK == glFace) {
1792 // we call the combined func just in case separate stencil is not
1793 // supported.
1794 GR_GL_CALL(gl, StencilFunc(glFunc, ref, mask));
1795 GR_GL_CALL(gl, StencilMask(writeMask));
1796 GR_GL_CALL(gl, StencilOp(glFailOp, glPassOp, glPassOp));
1797 } else {
1798 GR_GL_CALL(gl, StencilFuncSeparate(glFace, glFunc, ref, mask));
1799 GR_GL_CALL(gl, StencilMaskSeparate(glFace, writeMask));
1800 GR_GL_CALL(gl, StencilOpSeparate(glFace, glFailOp, glPassOp, glPassOp));
1801 }
1802}
1803}
bsalomon@google.comd302f142011-03-03 13:54:13 +00001804
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001805void GrGpuGL::flushStencil(DrawType type) {
1806 if (kStencilPath_DrawType == type) {
1807 GrAssert(!fStencilSettings.isTwoSided());
1808 // Just the func, ref, and mask is set here. The op and write mask are params to the call
1809 // that draws the path to the SB (glStencilFillPath)
1810 GrGLenum func =
1811 gr_to_gl_stencil_func(fStencilSettings.func(GrStencilSettings::kFront_Face));
1812 GL_CALL(PathStencilFunc(func,
1813 fStencilSettings.funcRef(GrStencilSettings::kFront_Face),
1814 fStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
1815 } else if (fHWStencilSettings != fStencilSettings) {
1816 if (fStencilSettings.isDisabled()) {
1817 if (kNo_TriState != fHWStencilTestEnabled) {
1818 GL_CALL(Disable(GR_GL_STENCIL_TEST));
1819 fHWStencilTestEnabled = kNo_TriState;
1820 }
1821 } else {
1822 if (kYes_TriState != fHWStencilTestEnabled) {
1823 GL_CALL(Enable(GR_GL_STENCIL_TEST));
1824 fHWStencilTestEnabled = kYes_TriState;
1825 }
bsalomon@google.coma3201942012-06-21 19:58:20 +00001826 }
bsalomon@google.coma3201942012-06-21 19:58:20 +00001827 if (!fStencilSettings.isDisabled()) {
bsalomon@google.combcce8922013-03-25 15:38:39 +00001828 if (this->caps()->twoSidedStencilSupport()) {
bsalomon@google.com411dad02012-06-05 20:24:20 +00001829 set_gl_stencil(this->glInterface(),
bsalomon@google.coma3201942012-06-21 19:58:20 +00001830 fStencilSettings,
bsalomon@google.com411dad02012-06-05 20:24:20 +00001831 GR_GL_FRONT,
bsalomon@google.coma3201942012-06-21 19:58:20 +00001832 GrStencilSettings::kFront_Face);
bsalomon@google.com411dad02012-06-05 20:24:20 +00001833 set_gl_stencil(this->glInterface(),
bsalomon@google.coma3201942012-06-21 19:58:20 +00001834 fStencilSettings,
bsalomon@google.com411dad02012-06-05 20:24:20 +00001835 GR_GL_BACK,
bsalomon@google.coma3201942012-06-21 19:58:20 +00001836 GrStencilSettings::kBack_Face);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001837 } else {
bsalomon@google.com411dad02012-06-05 20:24:20 +00001838 set_gl_stencil(this->glInterface(),
bsalomon@google.coma3201942012-06-21 19:58:20 +00001839 fStencilSettings,
bsalomon@google.com411dad02012-06-05 20:24:20 +00001840 GR_GL_FRONT_AND_BACK,
bsalomon@google.coma3201942012-06-21 19:58:20 +00001841 GrStencilSettings::kFront_Face);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001842 }
1843 }
bsalomon@google.coma3201942012-06-21 19:58:20 +00001844 fHWStencilSettings = fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001845 }
1846}
1847
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001848void GrGpuGL::flushAAState(DrawType type) {
bsalomon@google.com202d1392013-03-19 18:58:08 +00001849// At least some ATI linux drivers will render GL_LINES incorrectly when MSAA state is enabled but
1850// the target is not multisampled. Single pixel wide lines are rendered thicker than 1 pixel wide.
1851#if 0
1852 // Replace RT_HAS_MSAA with this definition once this driver bug is no longer a relevant concern
1853 #define RT_HAS_MSAA rt->isMultisampled()
1854#else
1855 #define RT_HAS_MSAA (rt->isMultisampled() || kDrawLines_DrawType == type)
1856#endif
1857
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001858 const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001859 if (kDesktop_GrGLBinding == this->glBinding()) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001860 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1861 // smooth lines.
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001862 // we prefer smooth lines over multisampled lines
bsalomon@google.com4d5f3fe2012-05-21 17:11:44 +00001863 bool smoothLines = false;
1864
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001865 if (kDrawLines_DrawType == type) {
bsalomon@google.com4d5f3fe2012-05-21 17:11:44 +00001866 smoothLines = this->willUseHWAALines();
1867 if (smoothLines) {
1868 if (kYes_TriState != fHWAAState.fSmoothLineEnabled) {
1869 GL_CALL(Enable(GR_GL_LINE_SMOOTH));
1870 fHWAAState.fSmoothLineEnabled = kYes_TriState;
1871 // must disable msaa to use line smoothing
bsalomon@google.com202d1392013-03-19 18:58:08 +00001872 if (RT_HAS_MSAA &&
bsalomon@google.com4d5f3fe2012-05-21 17:11:44 +00001873 kNo_TriState != fHWAAState.fMSAAEnabled) {
1874 GL_CALL(Disable(GR_GL_MULTISAMPLE));
1875 fHWAAState.fMSAAEnabled = kNo_TriState;
1876 }
1877 }
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001878 } else {
bsalomon@google.com4d5f3fe2012-05-21 17:11:44 +00001879 if (kNo_TriState != fHWAAState.fSmoothLineEnabled) {
1880 GL_CALL(Disable(GR_GL_LINE_SMOOTH));
1881 fHWAAState.fSmoothLineEnabled = kNo_TriState;
1882 }
1883 }
1884 }
bsalomon@google.com202d1392013-03-19 18:58:08 +00001885 if (!smoothLines && RT_HAS_MSAA) {
bsalomon@google.comded4f4b2012-06-28 18:48:06 +00001886 // FIXME: GL_NV_pr doesn't seem to like MSAA disabled. The paths
1887 // convex hulls of each segment appear to get filled.
1888 bool enableMSAA = kStencilPath_DrawType == type ||
1889 this->getDrawState().isHWAntialiasState();
1890 if (enableMSAA) {
bsalomon@google.com4d5f3fe2012-05-21 17:11:44 +00001891 if (kYes_TriState != fHWAAState.fMSAAEnabled) {
1892 GL_CALL(Enable(GR_GL_MULTISAMPLE));
1893 fHWAAState.fMSAAEnabled = kYes_TriState;
1894 }
1895 } else {
1896 if (kNo_TriState != fHWAAState.fMSAAEnabled) {
1897 GL_CALL(Disable(GR_GL_MULTISAMPLE));
1898 fHWAAState.fMSAAEnabled = kNo_TriState;
1899 }
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001900 }
1901 }
1902 }
1903}
1904
bsalomon@google.com64aef2b2012-06-11 15:36:13 +00001905void GrGpuGL::flushBlend(bool isLines,
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001906 GrBlendCoeff srcCoeff,
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001907 GrBlendCoeff dstCoeff) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +00001908 if (isLines && this->willUseHWAALines()) {
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +00001909 if (kYes_TriState != fHWBlendState.fEnabled) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001910 GL_CALL(Enable(GR_GL_BLEND));
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +00001911 fHWBlendState.fEnabled = kYes_TriState;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001912 }
bsalomon@google.com47059542012-06-06 20:51:20 +00001913 if (kSA_GrBlendCoeff != fHWBlendState.fSrcCoeff ||
1914 kISA_GrBlendCoeff != fHWBlendState.fDstCoeff) {
1915 GL_CALL(BlendFunc(gXfermodeCoeff2Blend[kSA_GrBlendCoeff],
1916 gXfermodeCoeff2Blend[kISA_GrBlendCoeff]));
1917 fHWBlendState.fSrcCoeff = kSA_GrBlendCoeff;
1918 fHWBlendState.fDstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001919 }
1920 } else {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001921 // any optimization to disable blending should
1922 // have already been applied and tweaked the coeffs
1923 // to (1, 0).
bsalomon@google.com47059542012-06-06 20:51:20 +00001924 bool blendOff = kOne_GrBlendCoeff == srcCoeff &&
1925 kZero_GrBlendCoeff == dstCoeff;
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +00001926 if (blendOff) {
1927 if (kNo_TriState != fHWBlendState.fEnabled) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001928 GL_CALL(Disable(GR_GL_BLEND));
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +00001929 fHWBlendState.fEnabled = kNo_TriState;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001930 }
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +00001931 } else {
1932 if (kYes_TriState != fHWBlendState.fEnabled) {
1933 GL_CALL(Enable(GR_GL_BLEND));
1934 fHWBlendState.fEnabled = kYes_TriState;
1935 }
1936 if (fHWBlendState.fSrcCoeff != srcCoeff ||
1937 fHWBlendState.fDstCoeff != dstCoeff) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001938 GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1939 gXfermodeCoeff2Blend[dstCoeff]));
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +00001940 fHWBlendState.fSrcCoeff = srcCoeff;
1941 fHWBlendState.fDstCoeff = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001942 }
bsalomon@google.coma5d056a2012-03-27 15:59:58 +00001943 GrColor blendConst = this->getDrawState().getBlendConstant();
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001944 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1945 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +00001946 (!fHWBlendState.fConstColorValid ||
1947 fHWBlendState.fConstColor != blendConst)) {
bsalomon@google.com75347472012-09-17 17:23:21 +00001948 GrGLfloat c[4];
1949 GrColorToRGBAFloat(blendConst, c);
bsalomon@google.com0b77d682011-08-19 13:28:54 +00001950 GL_CALL(BlendColor(c[0], c[1], c[2], c[3]));
bsalomon@google.coma4d8fc22012-05-21 13:21:46 +00001951 fHWBlendState.fConstColor = blendConst;
1952 fHWBlendState.fConstColorValid = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001953 }
1954 }
1955 }
1956}
bsalomon@google.com0a97be22011-11-08 19:20:57 +00001957namespace {
1958
bsalomon@google.com6d003d12012-09-11 15:45:20 +00001959inline void set_tex_swizzle(GrGLenum swizzle[4], const GrGLInterface* gl) {
bsalomon@google.com4d063de2012-05-31 17:59:23 +00001960 GR_GL_CALL(gl, TexParameteriv(GR_GL_TEXTURE_2D,
1961 GR_GL_TEXTURE_SWIZZLE_RGBA,
1962 reinterpret_cast<const GrGLint*>(swizzle)));
bsalomon@google.com0a97be22011-11-08 19:20:57 +00001963}
bsalomon@google.comb8670992012-07-25 21:27:09 +00001964
bsalomon@google.com6c76d242012-09-07 16:52:24 +00001965inline GrGLenum tile_to_gl_wrap(SkShader::TileMode tm) {
bsalomon@google.comb8670992012-07-25 21:27:09 +00001966 static const GrGLenum gWrapModes[] = {
1967 GR_GL_CLAMP_TO_EDGE,
1968 GR_GL_REPEAT,
1969 GR_GL_MIRRORED_REPEAT
1970 };
1971 GrAssert((unsigned) tm <= SK_ARRAY_COUNT(gWrapModes));
1972 GR_STATIC_ASSERT(0 == SkShader::kClamp_TileMode);
1973 GR_STATIC_ASSERT(1 == SkShader::kRepeat_TileMode);
1974 GR_STATIC_ASSERT(2 == SkShader::kMirror_TileMode);
1975 return gWrapModes[tm];
1976}
1977
bsalomon@google.com0a97be22011-11-08 19:20:57 +00001978}
1979
bsalomon@google.com34cccde2013-01-04 18:34:30 +00001980void GrGpuGL::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture) {
1981 GrAssert(NULL != texture);
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001982
bsalomon@google.comb8670992012-07-25 21:27:09 +00001983 // If we created a rt/tex and rendered to it without using a texture and now we're texturing
1984 // from the rt it will still be the last bound texture, but it needs resolving. So keep this
bsalomon@google.com4c883782012-06-04 19:05:11 +00001985 // out of the "last != next" check.
bsalomon@google.com34cccde2013-01-04 18:34:30 +00001986 GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
bsalomon@google.com4c883782012-06-04 19:05:11 +00001987 if (NULL != texRT) {
1988 this->onResolveRenderTarget(texRT);
1989 }
1990
bsalomon@google.com34cccde2013-01-04 18:34:30 +00001991 if (fHWBoundTextures[unitIdx] != texture) {
1992 this->setTextureUnit(unitIdx);
1993 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, texture->textureID()));
1994 fHWBoundTextures[unitIdx] = texture;
bsalomon@google.com4c883782012-06-04 19:05:11 +00001995 }
1996
bsalomon@google.com4c883782012-06-04 19:05:11 +00001997 ResetTimestamp timestamp;
bsalomon@google.com34cccde2013-01-04 18:34:30 +00001998 const GrGLTexture::TexParams& oldTexParams = texture->getCachedTexParams(&timestamp);
bsalomon@google.com4c883782012-06-04 19:05:11 +00001999 bool setAll = timestamp < this->getResetTimestamp();
2000 GrGLTexture::TexParams newTexParams;
2001
bsalomon@google.comb8670992012-07-25 21:27:09 +00002002 newTexParams.fFilter = params.isBilerp() ? GR_GL_LINEAR : GR_GL_NEAREST;
bsalomon@google.com4c883782012-06-04 19:05:11 +00002003
bsalomon@google.comb8670992012-07-25 21:27:09 +00002004 newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX());
2005 newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY());
bsalomon@google.com4c883782012-06-04 19:05:11 +00002006 memcpy(newTexParams.fSwizzleRGBA,
bsalomon@google.com34cccde2013-01-04 18:34:30 +00002007 GrGLShaderBuilder::GetTexParamSwizzle(texture->config(), this->glCaps()),
bsalomon@google.com4c883782012-06-04 19:05:11 +00002008 sizeof(newTexParams.fSwizzleRGBA));
2009 if (setAll || newTexParams.fFilter != oldTexParams.fFilter) {
bsalomon@google.com34cccde2013-01-04 18:34:30 +00002010 this->setTextureUnit(unitIdx);
bsalomon@google.com4c883782012-06-04 19:05:11 +00002011 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2012 GR_GL_TEXTURE_MAG_FILTER,
2013 newTexParams.fFilter));
2014 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2015 GR_GL_TEXTURE_MIN_FILTER,
2016 newTexParams.fFilter));
2017 }
2018 if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) {
bsalomon@google.com34cccde2013-01-04 18:34:30 +00002019 this->setTextureUnit(unitIdx);
bsalomon@google.com4c883782012-06-04 19:05:11 +00002020 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2021 GR_GL_TEXTURE_WRAP_S,
2022 newTexParams.fWrapS));
2023 }
2024 if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) {
bsalomon@google.com34cccde2013-01-04 18:34:30 +00002025 this->setTextureUnit(unitIdx);
bsalomon@google.com4c883782012-06-04 19:05:11 +00002026 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
2027 GR_GL_TEXTURE_WRAP_T,
2028 newTexParams.fWrapT));
2029 }
2030 if (this->glCaps().textureSwizzleSupport() &&
2031 (setAll || memcmp(newTexParams.fSwizzleRGBA,
2032 oldTexParams.fSwizzleRGBA,
2033 sizeof(newTexParams.fSwizzleRGBA)))) {
bsalomon@google.com34cccde2013-01-04 18:34:30 +00002034 this->setTextureUnit(unitIdx);
bsalomon@google.com4c883782012-06-04 19:05:11 +00002035 set_tex_swizzle(newTexParams.fSwizzleRGBA,
2036 this->glInterface());
2037 }
bsalomon@google.com34cccde2013-01-04 18:34:30 +00002038 texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
bsalomon@google.com4c883782012-06-04 19:05:11 +00002039}
2040
bsalomon@google.comc96cb3a2012-06-04 19:31:00 +00002041void GrGpuGL::flushMiscFixedFunctionState() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00002042
bsalomon@google.comc96cb3a2012-06-04 19:31:00 +00002043 const GrDrawState& drawState = this->getDrawState();
reed@google.comac10a2d2010-12-22 21:39:39 +00002044
bsalomon@google.comc96cb3a2012-06-04 19:31:00 +00002045 if (drawState.isDitherState()) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00002046 if (kYes_TriState != fHWDitherEnabled) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00002047 GL_CALL(Enable(GR_GL_DITHER));
bsalomon@google.com978c8c62012-05-21 14:45:49 +00002048 fHWDitherEnabled = kYes_TriState;
2049 }
2050 } else {
2051 if (kNo_TriState != fHWDitherEnabled) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00002052 GL_CALL(Disable(GR_GL_DITHER));
bsalomon@google.com978c8c62012-05-21 14:45:49 +00002053 fHWDitherEnabled = kNo_TriState;
reed@google.comac10a2d2010-12-22 21:39:39 +00002054 }
2055 }
2056
bsalomon@google.comc96cb3a2012-06-04 19:31:00 +00002057 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00002058 if (kNo_TriState != fHWWriteToColor) {
2059 GL_CALL(ColorMask(GR_GL_FALSE, GR_GL_FALSE,
2060 GR_GL_FALSE, GR_GL_FALSE));
2061 fHWWriteToColor = kNo_TriState;
bsalomon@google.comd302f142011-03-03 13:54:13 +00002062 }
bsalomon@google.com978c8c62012-05-21 14:45:49 +00002063 } else {
2064 if (kYes_TriState != fHWWriteToColor) {
2065 GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
2066 fHWWriteToColor = kYes_TriState;
2067 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00002068 }
2069
bsalomon@google.comc96cb3a2012-06-04 19:31:00 +00002070 if (fHWDrawFace != drawState.getDrawFace()) {
bsalomon@google.coma5d056a2012-03-27 15:59:58 +00002071 switch (this->getDrawState().getDrawFace()) {
tomhudson@google.com93813632011-10-27 20:21:16 +00002072 case GrDrawState::kCCW_DrawFace:
bsalomon@google.com0b77d682011-08-19 13:28:54 +00002073 GL_CALL(Enable(GR_GL_CULL_FACE));
2074 GL_CALL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00002075 break;
tomhudson@google.com93813632011-10-27 20:21:16 +00002076 case GrDrawState::kCW_DrawFace:
bsalomon@google.com0b77d682011-08-19 13:28:54 +00002077 GL_CALL(Enable(GR_GL_CULL_FACE));
2078 GL_CALL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00002079 break;
tomhudson@google.com93813632011-10-27 20:21:16 +00002080 case GrDrawState::kBoth_DrawFace:
bsalomon@google.com0b77d682011-08-19 13:28:54 +00002081 GL_CALL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00002082 break;
2083 default:
2084 GrCrash("Unknown draw face.");
2085 }
bsalomon@google.comc96cb3a2012-06-04 19:31:00 +00002086 fHWDrawFace = drawState.getDrawFace();
bsalomon@google.comd302f142011-03-03 13:54:13 +00002087 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002088}
2089
reed@google.comac10a2d2010-12-22 21:39:39 +00002090void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
2091 GrAssert(NULL != renderTarget);
bsalomon@google.comc811ea32012-05-21 15:33:09 +00002092 if (fHWBoundRenderTarget == renderTarget) {
2093 fHWBoundRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00002094 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002095}
2096
2097void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
tomhudson@google.com93813632011-10-27 20:21:16 +00002098 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comc811ea32012-05-21 15:33:09 +00002099 if (fHWBoundTextures[s] == texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002100 // deleting bound texture does implied bind to 0
bsalomon@google.comc811ea32012-05-21 15:33:09 +00002101 fHWBoundTextures[s] = NULL;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002102 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002103 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002104}
2105
bsalomon@google.com280e99f2012-01-05 16:17:38 +00002106bool GrGpuGL::configToGLFormats(GrPixelConfig config,
2107 bool getSizedInternalFormat,
2108 GrGLenum* internalFormat,
2109 GrGLenum* externalFormat,
2110 GrGLenum* externalType) {
2111 GrGLenum dontCare;
2112 if (NULL == internalFormat) {
2113 internalFormat = &dontCare;
2114 }
2115 if (NULL == externalFormat) {
2116 externalFormat = &dontCare;
2117 }
2118 if (NULL == externalType) {
2119 externalType = &dontCare;
2120 }
2121
reed@google.comac10a2d2010-12-22 21:39:39 +00002122 switch (config) {
bsalomon@google.com0342a852012-08-20 19:22:38 +00002123 case kRGBA_8888_GrPixelConfig:
bsalomon@google.comc4364992011-11-07 15:54:49 +00002124 *internalFormat = GR_GL_RGBA;
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +00002125 *externalFormat = GR_GL_RGBA;
bsalomon@google.com280e99f2012-01-05 16:17:38 +00002126 if (getSizedInternalFormat) {
2127 *internalFormat = GR_GL_RGBA8;
2128 } else {
2129 *internalFormat = GR_GL_RGBA;
2130 }
bsalomon@google.com6f379512011-11-16 20:36:03 +00002131 *externalType = GR_GL_UNSIGNED_BYTE;
bsalomon@google.comc4364992011-11-07 15:54:49 +00002132 break;
bsalomon@google.com0342a852012-08-20 19:22:38 +00002133 case kBGRA_8888_GrPixelConfig:
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00002134 if (!this->glCaps().bgraFormatSupport()) {
bsalomon@google.comc4364992011-11-07 15:54:49 +00002135 return false;
2136 }
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00002137 if (this->glCaps().bgraIsInternalFormat()) {
bsalomon@google.com280e99f2012-01-05 16:17:38 +00002138 if (getSizedInternalFormat) {
2139 *internalFormat = GR_GL_BGRA8;
2140 } else {
2141 *internalFormat = GR_GL_BGRA;
2142 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002143 } else {
bsalomon@google.com280e99f2012-01-05 16:17:38 +00002144 if (getSizedInternalFormat) {
2145 *internalFormat = GR_GL_RGBA8;
2146 } else {
2147 *internalFormat = GR_GL_RGBA;
2148 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002149 }
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +00002150 *externalFormat = GR_GL_BGRA;
bsalomon@google.com6f379512011-11-16 20:36:03 +00002151 *externalType = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00002152 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002153 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002154 *internalFormat = GR_GL_RGB;
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +00002155 *externalFormat = GR_GL_RGB;
bsalomon@google.com280e99f2012-01-05 16:17:38 +00002156 if (getSizedInternalFormat) {
2157 if (this->glBinding() == kDesktop_GrGLBinding) {
2158 return false;
2159 } else {
2160 *internalFormat = GR_GL_RGB565;
2161 }
2162 } else {
2163 *internalFormat = GR_GL_RGB;
2164 }
bsalomon@google.com6f379512011-11-16 20:36:03 +00002165 *externalType = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00002166 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002167 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002168 *internalFormat = GR_GL_RGBA;
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +00002169 *externalFormat = GR_GL_RGBA;
bsalomon@google.com280e99f2012-01-05 16:17:38 +00002170 if (getSizedInternalFormat) {
2171 *internalFormat = GR_GL_RGBA4;
2172 } else {
2173 *internalFormat = GR_GL_RGBA;
2174 }
bsalomon@google.com6f379512011-11-16 20:36:03 +00002175 *externalType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002176 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002177 case kIndex_8_GrPixelConfig:
bsalomon@google.combcce8922013-03-25 15:38:39 +00002178 if (this->caps()->eightBitPaletteSupport()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002179 *internalFormat = GR_GL_PALETTE8_RGBA8;
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +00002180 // glCompressedTexImage doesn't take external params
2181 *externalFormat = GR_GL_PALETTE8_RGBA8;
bsalomon@google.com280e99f2012-01-05 16:17:38 +00002182 // no sized/unsized internal format distinction here
2183 *internalFormat = GR_GL_PALETTE8_RGBA8;
2184 // unused with CompressedTexImage
bsalomon@google.com32e4d2a2011-12-09 16:14:25 +00002185 *externalType = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00002186 } else {
2187 return false;
2188 }
2189 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002190 case kAlpha_8_GrPixelConfig:
robertphillips@google.com443e5a52012-04-30 20:01:21 +00002191 if (this->glCaps().textureRedSupport()) {
2192 *internalFormat = GR_GL_RED;
2193 *externalFormat = GR_GL_RED;
2194 if (getSizedInternalFormat) {
2195 *internalFormat = GR_GL_R8;
2196 } else {
2197 *internalFormat = GR_GL_RED;
2198 }
2199 *externalType = GR_GL_UNSIGNED_BYTE;
bsalomon@google.com280e99f2012-01-05 16:17:38 +00002200 } else {
2201 *internalFormat = GR_GL_ALPHA;
robertphillips@google.com443e5a52012-04-30 20:01:21 +00002202 *externalFormat = GR_GL_ALPHA;
2203 if (getSizedInternalFormat) {
2204 *internalFormat = GR_GL_ALPHA8;
2205 } else {
2206 *internalFormat = GR_GL_ALPHA;
2207 }
2208 *externalType = GR_GL_UNSIGNED_BYTE;
bsalomon@google.com280e99f2012-01-05 16:17:38 +00002209 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002210 break;
2211 default:
2212 return false;
2213 }
2214 return true;
2215}
2216
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002217void GrGpuGL::setTextureUnit(int unit) {
tomhudson@google.com93813632011-10-27 20:21:16 +00002218 GrAssert(unit >= 0 && unit < GrDrawState::kNumStages);
bsalomon@google.com49209392012-06-05 15:13:46 +00002219 if (fHWActiveTextureUnitIdx != unit) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00002220 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com49209392012-06-05 15:13:46 +00002221 fHWActiveTextureUnitIdx = unit;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002222 }
2223}
bsalomon@google.com316f99232011-01-13 21:28:12 +00002224
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002225void GrGpuGL::setSpareTextureUnit() {
bsalomon@google.com49209392012-06-05 15:13:46 +00002226 if (fHWActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +00002227 GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com49209392012-06-05 15:13:46 +00002228 fHWActiveTextureUnitIdx = SPARE_TEX_UNIT;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002229 }
2230}
2231
bsalomon@google.com880b8fc2013-02-19 20:17:28 +00002232///////////////////////////////////////////////////////////////////////////////
2233
bsalomon@google.com6918d482013-03-07 19:09:11 +00002234GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw(
2235 GrGpuGL* gpu,
2236 const GrGLVertexBuffer* vbuffer,
2237 const GrGLIndexBuffer* ibuffer) {
2238 GrAssert(NULL != vbuffer);
robertphillips@google.com4f65a272013-03-26 19:40:46 +00002239 GrGLAttribArrayState* attribState;
2240
bsalomon@google.com6918d482013-03-07 19:09:11 +00002241 // We use a vertex array if we're on a core profile and the verts are in a VBO.
2242 if (gpu->glCaps().isCoreProfile() && !vbuffer->isCPUBacked()) {
2243 if (NULL == fVBOVertexArray || !fVBOVertexArray->isValid()) {
2244 SkSafeUnref(fVBOVertexArray);
2245 GrGLuint arrayID;
2246 GR_GL_CALL(gpu->glInterface(), GenVertexArrays(1, &arrayID));
2247 int attrCount = gpu->glCaps().maxVertexAttributes();
2248 fVBOVertexArray = SkNEW_ARGS(GrGLVertexArray, (gpu, arrayID, attrCount));
bsalomon@google.com880b8fc2013-02-19 20:17:28 +00002249 }
bsalomon@google.com6918d482013-03-07 19:09:11 +00002250 attribState = fVBOVertexArray->bindWithIndexBuffer(ibuffer);
2251 } else {
2252 if (NULL != ibuffer) {
2253 this->setIndexBufferIDOnDefaultVertexArray(gpu, ibuffer->bufferID());
2254 } else {
2255 this->setVertexArrayID(gpu, 0);
2256 }
2257 int attrCount = gpu->glCaps().maxVertexAttributes();
2258 if (fDefaultVertexArrayAttribState.count() != attrCount) {
2259 fDefaultVertexArrayAttribState.resize(attrCount);
2260 }
2261 attribState = &fDefaultVertexArrayAttribState;
bsalomon@google.com880b8fc2013-02-19 20:17:28 +00002262 }
bsalomon@google.com6918d482013-03-07 19:09:11 +00002263 return attribState;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002264}