blob: 8d00af9ce2e683227e6bc5ac351ded391980bb72 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#include "GrGpuGL.h"
18#include "GrMemory.h"
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +000019#if GR_WIN32_BUILD
20 // need to get wglGetProcAddress
21 #undef WIN32_LEAN_AND_MEAN
22 #define WIN32_LEAN_AND_MEAN 1
23 #include <windows.h>
24 #undef WIN32_LEAN_AND_MEAN
25#endif
26
reed@google.comac10a2d2010-12-22 21:39:39 +000027
28static const GLuint GR_MAX_GLUINT = ~0;
29static const GLint GR_INVAL_GLINT = ~0;
30
bsalomon@google.com316f99232011-01-13 21:28:12 +000031// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000032// mucking with the state of any of the stages.
bsalomon@google.com316f99232011-01-13 21:28:12 +000033static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000034
reed@google.comac10a2d2010-12-22 21:39:39 +000035#define SKIP_CACHE_CHECK true
36
37static const GLenum gXfermodeCoeff2Blend[] = {
38 GL_ZERO,
39 GL_ONE,
40 GL_SRC_COLOR,
41 GL_ONE_MINUS_SRC_COLOR,
42 GL_DST_COLOR,
43 GL_ONE_MINUS_DST_COLOR,
44 GL_SRC_ALPHA,
45 GL_ONE_MINUS_SRC_ALPHA,
46 GL_DST_ALPHA,
47 GL_ONE_MINUS_DST_ALPHA,
48};
49
reed@google.comac10a2d2010-12-22 21:39:39 +000050///////////////////////////////////////////////////////////////////////////////
51
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +000052static bool gPrintStartupSpew;
53
54
reed@google.comac10a2d2010-12-22 21:39:39 +000055bool fbo_test(GrGLExts exts, int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000056
57 GLint savedFBO;
58 GLint savedTexUnit;
reed@google.com3d8de042011-01-20 02:18:00 +000059 GR_GL_GetIntegerv(GL_ACTIVE_TEXTURE, &savedTexUnit);
60 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +000061
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000062 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +000063
reed@google.comac10a2d2010-12-22 21:39:39 +000064 GLuint testFBO;
65 GR_GLEXT(exts, GenFramebuffers(1, &testFBO));
66 GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, testFBO));
67 GLuint testRTTex;
68 GR_GL(GenTextures(1, &testRTTex));
69 GR_GL(BindTexture(GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +000070 // some implementations require texture to be mip-map complete before
71 // FBO with level 0 bound as color attachment will be framebuffer complete.
72 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +000073 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h,
74 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
75 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
76 GR_GLEXT(exts, FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0,
77 GL_TEXTURE_2D, testRTTex, 0));
78 GLenum status = GR_GLEXT(exts, CheckFramebufferStatus(GR_FRAMEBUFFER));
79 GR_GLEXT(exts, DeleteFramebuffers(1, &testFBO));
80 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +000081
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000082 GR_GL(ActiveTexture(savedTexUnit));
83 GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +000084
reed@google.comac10a2d2010-12-22 21:39:39 +000085 return status == GR_FRAMEBUFFER_COMPLETE;
86}
87
reed@google.comac10a2d2010-12-22 21:39:39 +000088GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +000089
reed@google.comeeeb5a02010-12-23 15:12:59 +000090 if (gPrintStartupSpew) {
91 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
92 this);
93 GrPrintf("------ VENDOR %s\n", glGetString(GL_VENDOR));
94 GrPrintf("------ RENDERER %s\n", glGetString(GL_RENDERER));
95 GrPrintf("------ VERSION %s\n", glGetString(GL_VERSION));
96 GrPrintf("------ EXTENSIONS\n %s \n", glGetString(GL_EXTENSIONS));
97 }
reed@google.comac10a2d2010-12-22 21:39:39 +000098
99 GrGLClearErr();
100
101 GrGLInitExtensions(&fExts);
102
103 resetContextHelper();
104
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000105 fHWDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000106 fRenderTargetChanged = true;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000107
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000108 GLint maxTextureUnits;
109 // check FS and fixed-function texture unit limits
110 // we only use textures in the fragment stage currently.
111 // checks are > to make sure we have a spare unit.
112#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES2
reed@google.com3d8de042011-01-20 02:18:00 +0000113 GR_GL_GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000114 GrAssert(maxTextureUnits > kNumStages);
115#endif
116#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1
reed@google.com3d8de042011-01-20 02:18:00 +0000117 GR_GL_GetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000118 GrAssert(maxTextureUnits > kNumStages);
119#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +0000120
reed@google.comac10a2d2010-12-22 21:39:39 +0000121 fCurrDrawState = fHWDrawState;
122
123 ////////////////////////////////////////////////////////////////////////////
124 // Check for supported features.
125
126 int major, minor;
127 gl_version(&major, &minor);
128
129 GLint numFormats;
reed@google.comac20fb92011-01-12 17:14:53 +0000130 GR_GL_GetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000131 GrAutoSTMalloc<10, GLint> formats(numFormats);
reed@google.comac20fb92011-01-12 17:14:53 +0000132 GR_GL_GetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000133 for (int i = 0; i < numFormats; ++i) {
134 if (formats[i] == GR_PALETTE8_RGBA8) {
135 f8bitPaletteSupport = true;
136 break;
137 }
138 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000139
140 if (gPrintStartupSpew) {
141 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
142 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000143
144 GR_STATIC_ASSERT(0 == kNone_AALevel);
145 GR_STATIC_ASSERT(1 == kLow_AALevel);
146 GR_STATIC_ASSERT(2 == kMed_AALevel);
147 GR_STATIC_ASSERT(3 == kHigh_AALevel);
148
149 memset(fAASamples, 0, sizeof(fAASamples));
150 fMSFBOType = kNone_MSFBO;
151 if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
152 fMSFBOType = kIMG_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000153 if (gPrintStartupSpew) {
154 GrPrintf("MSAA Support: IMG ES EXT.\n");
155 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000156 }
157 else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
158 fMSFBOType = kApple_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000159 if (gPrintStartupSpew) {
160 GrPrintf("MSAA Support: APPLE ES EXT.\n");
161 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000162 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000163#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000164 else if ((major >= 3) ||
165 has_gl_extension("GL_ARB_framebuffer_object") ||
166 (has_gl_extension("GL_EXT_framebuffer_multisample") &&
167 has_gl_extension("GL_EXT_framebuffer_blit"))) {
168 fMSFBOType = kDesktop_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000169 if (gPrintStartupSpew) {
170 GrPrintf("MSAA Support: DESKTOP\n");
171 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000172 }
173#endif
174 else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000175 if (gPrintStartupSpew) {
176 GrPrintf("MSAA Support: NONE\n");
177 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000178 }
179
180 if (kNone_MSFBO != fMSFBOType) {
181 GLint maxSamples;
182 GLenum maxSampleGetter = (kIMG_MSFBO == fMSFBOType) ?
183 GR_MAX_SAMPLES_IMG :
184 GR_MAX_SAMPLES;
reed@google.comac20fb92011-01-12 17:14:53 +0000185 GR_GL_GetIntegerv(maxSampleGetter, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000186 if (maxSamples > 1 ) {
187 fAASamples[kNone_AALevel] = 0;
188 fAASamples[kLow_AALevel] = GrMax(2,
189 GrFixedFloorToInt((GR_FixedHalf) *
190 maxSamples));
191 fAASamples[kMed_AALevel] = GrMax(2,
192 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
193 maxSamples));
194 fAASamples[kHigh_AALevel] = maxSamples;
195 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000196 if (gPrintStartupSpew) {
197 GrPrintf("\tMax Samples: %d\n", maxSamples);
198 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000199 }
200
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000201#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000202 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
203 has_gl_extension("GL_EXT_stencil_wrap");
204#else
205 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
206#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000207 if (gPrintStartupSpew) {
208 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
209 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000210
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000211#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000212 // we could also look for GL_ATI_separate_stencil extension or
213 // GL_EXT_stencil_two_side but they use different function signatures
214 // than GL2.0+ (and than each other).
215 fSingleStencilPassForWinding = (major >= 2);
216#else
217 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
218 // an ES1 extension.
219 fSingleStencilPassForWinding = (major >= 2);
220#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000221 if (gPrintStartupSpew) {
222 GrPrintf("Single Stencil Pass For Winding: %s\n", (fSingleStencilPassForWinding ? "YES" : "NO"));
223 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000224
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000225#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000226 fRGBA8Renderbuffer = true;
227#else
228 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
229#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000230 if (gPrintStartupSpew) {
231 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
232 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000233
bsalomon@google.comed3a0682011-01-18 16:54:04 +0000234#if GR_SUPPORT_GLES
235 if (GR_GL_32BPP_COLOR_FORMAT == GR_BGRA) {
236 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
237 }
238#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000239
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000240#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000241 fBufferLockSupport = true; // we require VBO support and the desktop VBO
242 // extension includes glMapBuffer.
243#else
244 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
245#endif
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000246
reed@google.comeeeb5a02010-12-23 15:12:59 +0000247 if (gPrintStartupSpew) {
248 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
249 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000250
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000251#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com0748f212011-02-01 22:56:16 +0000252 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
253 fNPOTTextureTileSupport = true;
254 fNPOTTextureSupport = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000255 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000256 fNPOTTextureTileSupport = false;
257 fNPOTTextureSupport = false;
258 }
259#else
260 if (major >= 2) {
261 fNPOTTextureSupport = true;
262 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
263 } else {
264 fNPOTTextureSupport = has_gl_extension("GL_APPLE_texture_2D_limited_npot");
265 fNPOTTextureTileSupport = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000266 }
267#endif
268 ////////////////////////////////////////////////////////////////////////////
269 // Experiments to determine limitations that can't be queried. TODO: Make
270 // these a preprocess that generate some compile time constants.
271
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000272 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000273
bsalomon@google.com0748f212011-02-01 22:56:16 +0000274 bool simpleFBOSuccess = fbo_test(fExts, 128, 128);
275 if (gPrintStartupSpew) {
276 if (!simpleFBOSuccess) {
277 GrPrintf("FBO Sanity Test: FAILED\n");
278 } else {
279 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000280 }
281 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000282 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000283
reed@google.comac10a2d2010-12-22 21:39:39 +0000284 /* Experimentation has found that some GLs that support NPOT textures
285 do not support FBOs with a NPOT texture. They report "unsupported" FBO
286 status. I don't know how to explicitly query for this. Do an
287 experiment. Note they may support NPOT with a renderbuffer but not a
288 texture. Presumably, the implementation bloats the renderbuffer
289 internally to the next POT.
290 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000291 bool fNPOTRenderTargetSupport = false;
292 if (fNPOTTextureSupport) {
293 fNPOTRenderTargetSupport = fbo_test(fExts, 200, 200);
294 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000295
bsalomon@google.com0748f212011-02-01 22:56:16 +0000296 if (gPrintStartupSpew) {
297 if (fNPOTTextureSupport) {
298 GrPrintf("NPOT textures supported\n");
299 if (fNPOTTextureTileSupport) {
300 GrPrintf("NPOT texture tiling supported\n");
301 } else {
302 GrPrintf("NPOT texture tiling NOT supported\n");
303 }
304 if (fNPOTRenderTargetSupport) {
305 GrPrintf("NPOT render targets supported\n");
306 } else {
307 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000308 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000309 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000310 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000311 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000312 }
313
reed@google.comac10a2d2010-12-22 21:39:39 +0000314 /* The iPhone 4 has a restriction that for an FBO with texture color
315 attachment with height <= 8 then the width must be <= height. Here
316 we look for such a limitation.
317 */
318 fMinRenderTargetHeight = GR_INVAL_GLINT;
319 GLint maxRenderSize;
reed@google.comac20fb92011-01-12 17:14:53 +0000320 GR_GL_GetIntegerv(GR_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000321
reed@google.comeeeb5a02010-12-23 15:12:59 +0000322 if (gPrintStartupSpew) {
323 GrPrintf("Small height FBO texture experiments\n");
324 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000325
326 for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000327 GLuint w = maxRenderSize;
328 GLuint h = i;
329 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000330 if (gPrintStartupSpew) {
331 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
332 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000333 fMinRenderTargetHeight = i;
334 break;
335 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000336 if (gPrintStartupSpew) {
337 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
338 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000339 }
340 }
341 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
342
reed@google.comeeeb5a02010-12-23 15:12:59 +0000343 if (gPrintStartupSpew) {
344 GrPrintf("Small width FBO texture experiments\n");
345 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000346 fMinRenderTargetWidth = GR_MAX_GLUINT;
bsalomon@google.com0748f212011-02-01 22:56:16 +0000347 for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000348 GLuint w = i;
349 GLuint h = maxRenderSize;
350 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000351 if (gPrintStartupSpew) {
352 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
353 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000354 fMinRenderTargetWidth = i;
355 break;
356 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000357 if (gPrintStartupSpew) {
358 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
359 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000360 }
361 }
362 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
363
reed@google.com02a7e6c2011-01-28 21:21:49 +0000364 GR_GL_GetIntegerv(GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000365}
366
367GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000368}
369
370void GrGpuGL::resetContextHelper() {
371// We detect cases when blending is effectively off
372 fHWBlendDisabled = false;
373 GR_GL(Enable(GL_BLEND));
374
375 // this is always disabled
376 GR_GL(Disable(GL_CULL_FACE));
377
378 GR_GL(Disable(GL_DITHER));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000379#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000380 GR_GL(Disable(GL_LINE_SMOOTH));
381 GR_GL(Disable(GL_POINT_SMOOTH));
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000382 GR_GL(Disable(GL_MULTISAMPLE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000383#endif
384
385 // we only ever use lines in hairline mode
386 GR_GL(LineWidth(1));
387
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000388 // invalid
389 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000390
391 fHWDrawState.fFlagBits = 0;
392
393 // illegal values
394 fHWDrawState.fSrcBlend = (BlendCoeff)-1;
395 fHWDrawState.fDstBlend = (BlendCoeff)-1;
396 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000397
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000398 fHWDrawState.fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax); // illegal
bsalomon@google.com316f99232011-01-13 21:28:12 +0000399
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000400 for (int s = 0; s < kNumStages; ++s) {
401 fHWDrawState.fTextures[s] = NULL;
402 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
403 -GR_ScalarMax,
404 true);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000405 fHWDrawState.fTextureMatrices[s].setScale(GR_ScalarMax, GR_ScalarMax);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000406 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000407
reed@google.comac10a2d2010-12-22 21:39:39 +0000408 GR_GL(Scissor(0,0,0,0));
409 fHWBounds.fScissorRect.setLTRB(0,0,0,0);
410 fHWBounds.fScissorEnabled = false;
411 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000412 fHWBounds.fViewportRect.setLTRB(-1,-1,-1,-1);
reed@google.comac10a2d2010-12-22 21:39:39 +0000413
reed@google.comac10a2d2010-12-22 21:39:39 +0000414 // disabling the stencil test also disables
415 // stencil buffer writes
416 GR_GL(Disable(GL_STENCIL_TEST));
417 GR_GL(StencilMask(0xffffffff));
418 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
419 fHWDrawState.fReverseFill = false;
420 fHWDrawState.fStencilPass = kNone_StencilPass;
421 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000422 fClipState.fClipIsDirty = true;
423 fClipState.fStencilClipTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000424
425 fHWGeometryState.fIndexBuffer = NULL;
426 fHWGeometryState.fVertexBuffer = NULL;
427 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
428 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000429 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000430
431 fHWDrawState.fRenderTarget = NULL;
432}
433
434void GrGpuGL::resetContext() {
435 INHERITED::resetContext();
436 resetContextHelper();
437}
438
reed@google.comac10a2d2010-12-22 21:39:39 +0000439GrRenderTarget* GrGpuGL::createPlatformRenderTarget(
440 intptr_t platformRenderTarget,
441 int width, int height) {
442 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
443 rtIDs.fStencilRenderbufferID = 0;
444 rtIDs.fMSColorRenderbufferID = 0;
445 rtIDs.fTexFBOID = 0;
446 rtIDs.fOwnIDs = false;
447
448 GrIRect viewport;
449
450 // viewport is in GL coords (top >= bottom)
451 viewport.setLTRB(0, height, width, 0);
452
453 rtIDs.fRTFBOID = (GLuint)platformRenderTarget;
454 rtIDs.fTexFBOID = (GLuint)platformRenderTarget;
455
456 GrGLRenderTarget* rt = new GrGLRenderTarget(rtIDs, viewport, NULL, this);
457
458 return rt;
459}
460
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000461GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000462
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000463 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000464
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000465 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&rtIDs.fRTFBOID);
466 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
467 rtIDs.fMSColorRenderbufferID = 0;
468 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000469
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000470 GLint vp[4];
471 GR_GL_GetIntegerv(GL_VIEWPORT, vp);
472 GrIRect viewportRect;
473 viewportRect.setLTRB(vp[0],
474 vp[1] + vp[3],
475 vp[0] + vp[2],
476 vp[1]);
477 rtIDs.fOwnIDs = false;
478
479 return new GrGLRenderTarget(rtIDs,
480 viewportRect,
481 NULL,
482 this);
483}
484
bsalomon@google.com5782d712011-01-21 21:03:59 +0000485///////////////////////////////////////////////////////////////////////////////
486
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000487// defines stencil formats from more to less preferred
reed@google.com63100f92011-01-18 21:32:14 +0000488GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = {
489 GR_STENCIL_INDEX8,
490
491#if GR_SUPPORT_GLDESKTOP
492 GR_STENCIL_INDEX16,
493#endif
494
495 GR_DEPTH24_STENCIL8,
496 GR_STENCIL_INDEX4,
497
498#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000499 GL_STENCIL_INDEX,
500 GR_DEPTH_STENCIL,
501#endif
502};
503
504// good to set a break-point here to know when createTexture fails
505static GrTexture* return_null_texture() {
506// GrAssert(!"null texture");
507 return NULL;
508}
509
510#if GR_DEBUG
511static size_t as_size_t(int x) {
512 return x;
513}
514#endif
515
reed@google.comac10a2d2010-12-22 21:39:39 +0000516GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
517 const void* srcData, size_t rowBytes) {
518
519#if GR_COLLECT_STATS
520 ++fStats.fTextureCreateCnt;
521#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000522
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000523 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000524
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000525 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
526 GL_NEAREST,
527 GL_CLAMP_TO_EDGE,
528 GL_CLAMP_TO_EDGE
529 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000530
reed@google.comac10a2d2010-12-22 21:39:39 +0000531 GrGLTexture::GLTextureDesc glDesc;
532 GLenum internalFormat;
533
534 glDesc.fContentWidth = desc.fWidth;
535 glDesc.fContentHeight = desc.fHeight;
536 glDesc.fAllocWidth = desc.fWidth;
537 glDesc.fAllocHeight = desc.fHeight;
538 glDesc.fFormat = desc.fFormat;
539
540 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
541 if (!canBeTexture(desc.fFormat,
542 &internalFormat,
543 &glDesc.fUploadFormat,
544 &glDesc.fUploadType)) {
545 return return_null_texture();
546 }
547
548 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
549 GLint samples = fAASamples[desc.fAALevel];
550 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
551 GrPrintf("AA RT requested but not supported on this platform.");
552 }
553
554 GR_GL(GenTextures(1, &glDesc.fTextureID));
555 if (!glDesc.fTextureID) {
556 return return_null_texture();
557 }
558
559 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
560
561 /*
562 * check if our srcData has extra bytes past each row. If so, we need
563 * to trim those off here, since GL doesn't let us pass the rowBytes as
564 * a parameter to glTexImage2D
565 */
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000566#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000567 if (srcData) {
568 GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH,
569 rowBytes / glDesc.fUploadByteCount));
570 }
571#else
572 GrAutoSMalloc<128 * 128> trimStorage;
573 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
574 if (srcData && (trimRowBytes < rowBytes)) {
575 size_t trimSize = desc.fHeight * trimRowBytes;
576 trimStorage.realloc(trimSize);
577 // now copy the data into our new storage, skipping the trailing bytes
578 const char* src = (const char*)srcData;
579 char* dst = (char*)trimStorage.get();
580 for (uint32_t y = 0; y < desc.fHeight; y++) {
581 memcpy(dst, src, trimRowBytes);
582 src += rowBytes;
583 dst += trimRowBytes;
584 }
585 // now point srcData to our trimmed version
586 srcData = trimStorage.get();
587 }
588#endif
589
reed@google.comac10a2d2010-12-22 21:39:39 +0000590 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000591 if (!this->npotRenderTargetSupport()) {
592 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
593 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
594 }
595
reed@google.comac10a2d2010-12-22 21:39:39 +0000596 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
597 glDesc.fAllocWidth);
598 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
599 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000600 } else if (!this->npotTextureSupport()) {
601 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
602 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000603 }
604
605 GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000606 GR_GL(TexParameteri(GL_TEXTURE_2D,
607 GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000608 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000609 GR_GL(TexParameteri(GL_TEXTURE_2D,
610 GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000611 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000612 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000613 GL_TEXTURE_WRAP_S,
614 DEFAULT_PARAMS.fWrapS));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000615 GR_GL(TexParameteri(GL_TEXTURE_2D,
616 GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000617 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000618
619 GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
620 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
621 supports8BitPalette()) {
622 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
623 GrAssert(desc.fWidth == glDesc.fAllocWidth);
624 GrAssert(desc.fHeight == glDesc.fAllocHeight);
625 GLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
626 kColorTableSize;
627 GR_GL(CompressedTexImage2D(GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
628 glDesc.fAllocWidth, glDesc.fAllocHeight,
629 0, imageSize, srcData));
630 GrGL_RestoreResetRowLength();
631 } else {
632 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
633 glDesc.fAllocHeight != desc.fHeight)) {
634 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat,
635 glDesc.fAllocWidth, glDesc.fAllocHeight,
636 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
637 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
638 desc.fHeight, glDesc.fUploadFormat,
639 glDesc.fUploadType, srcData));
640 GrGL_RestoreResetRowLength();
641
642 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
643 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
644 uint32_t maxTexels = extraW * extraH;
645 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
646 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
647
648 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
649
650 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
651 if (extraH) {
652 uint8_t* lastRowStart = (uint8_t*) srcData +
653 (desc.fHeight - 1) * rowSize;
654 uint8_t* extraRowStart = (uint8_t*)texels.get();
655
656 for (uint32_t i = 0; i < extraH; ++i) {
657 memcpy(extraRowStart, lastRowStart, rowSize);
658 extraRowStart += rowSize;
659 }
660 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
661 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
662 texels.get()));
663 }
664 if (extraW) {
665 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
666 uint8_t* extraTexel = (uint8_t*)texels.get();
667 for (uint32_t j = 0; j < desc.fHeight; ++j) {
668 for (uint32_t i = 0; i < extraW; ++i) {
669 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
670 extraTexel += glDesc.fUploadByteCount;
671 }
672 edgeTexel += rowSize;
673 }
674 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
675 desc.fHeight, glDesc.fUploadFormat,
676 glDesc.fUploadType, texels.get()));
677 }
678 if (extraW && extraH) {
679 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
680 - glDesc.fUploadByteCount;
681 uint8_t* extraTexel = (uint8_t*)texels.get();
682 for (uint32_t i = 0; i < extraW*extraH; ++i) {
683 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
684 extraTexel += glDesc.fUploadByteCount;
685 }
686 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
687 extraW, extraH, glDesc.fUploadFormat,
688 glDesc.fUploadType, texels.get()));
689 }
690
691 } else {
692 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
693 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
694 glDesc.fUploadType, srcData));
695 GrGL_RestoreResetRowLength();
696 }
697 }
698
699 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
700
701 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
702 rtIDs.fStencilRenderbufferID = 0;
703 rtIDs.fMSColorRenderbufferID = 0;
704 rtIDs.fRTFBOID = 0;
705 rtIDs.fTexFBOID = 0;
706 rtIDs.fOwnIDs = true;
707 GLenum msColorRenderbufferFormat = -1;
708
709 if (renderTarget) {
710#if GR_COLLECT_STATS
711 ++fStats.fRenderTargetCreateCnt;
712#endif
713 bool failed = true;
714 GLenum status;
715 GLint err;
716
717 // If need have both RT flag and srcData we have
718 // to invert the data before uploading because FBO
719 // will be rendered bottom up
720 GrAssert(NULL == srcData);
721 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
722
723 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fTexFBOID));
724 GrAssert(rtIDs.fTexFBOID);
725
726 // If we are using multisampling and any extension other than the IMG
727 // one we will create two FBOs. We render to one and then resolve to
728 // the texture bound to the other. The IMG extension does an implicit
729 // resolve.
730 if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
731 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fRTFBOID));
732 GrAssert(0 != rtIDs.fRTFBOID);
733 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
734 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
735 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
736 GR_GLEXT(fExts,
737 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
738 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
739 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
740 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000741 return return_null_texture();
742 }
743 } else {
744 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
745 }
746 int attempts = 1;
747 if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
748 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
749 GrAssert(0 != rtIDs.fStencilRenderbufferID);
750 attempts = GR_ARRAY_COUNT(GR_GL_STENCIL_FORMAT_ARRAY);
751 }
752
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000753 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000754 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000755 // (seems unlikely)
reed@google.comac10a2d2010-12-22 21:39:39 +0000756 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000757
758 err = ~GL_NO_ERROR;
759 for (int i = 0; i < attempts; ++i) {
760 if (rtIDs.fStencilRenderbufferID) {
761 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
762 rtIDs.fStencilRenderbufferID));
763 if (samples > 1) {
764 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
765 GR_RENDERBUFFER,
766 samples,
767 GR_GL_STENCIL_FORMAT_ARRAY[i],
768 glDesc.fAllocWidth,
769 glDesc.fAllocHeight));
770 } else {
771 GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
772 GR_RENDERBUFFER,
773 GR_GL_STENCIL_FORMAT_ARRAY[i],
774 glDesc.fAllocWidth,
775 glDesc.fAllocHeight));
776 }
777 err = glGetError();
778 if (err != GL_NO_ERROR) {
779 continue;
780 }
781 }
782 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
783 GrAssert(samples > 1);
784 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
785 rtIDs.fMSColorRenderbufferID));
786 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
787 GR_RENDERBUFFER,
788 samples,
789 msColorRenderbufferFormat,
790 glDesc.fAllocWidth,
791 glDesc.fAllocHeight));
792 err = glGetError();
793 if (err != GL_NO_ERROR) {
794 continue;
795 }
796 }
797 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
798
799#if GR_COLLECT_STATS
800 ++fStats.fRenderTargetChngCnt;
801#endif
802 if (kIMG_MSFBO == fMSFBOType && samples > 1) {
803 GR_GLEXT(fExts, FramebufferTexture2DMultisample(
804 GR_FRAMEBUFFER,
805 GR_COLOR_ATTACHMENT0,
806 GL_TEXTURE_2D,
807 glDesc.fTextureID,
808 0,
809 samples));
810
811 } else {
812 GR_GLEXT(fExts, FramebufferTexture2D(GR_FRAMEBUFFER,
813 GR_COLOR_ATTACHMENT0,
814 GL_TEXTURE_2D,
815 glDesc.fTextureID, 0));
816 }
817 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
818 GLenum status = GR_GLEXT(fExts,
819 CheckFramebufferStatus(GR_FRAMEBUFFER));
820 if (status != GR_FRAMEBUFFER_COMPLETE) {
821 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
822 status, desc.fWidth, desc.fHeight);
823 continue;
824 }
825 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
826 #if GR_COLLECT_STATS
827 ++fStats.fRenderTargetChngCnt;
828 #endif
829 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
830 GR_COLOR_ATTACHMENT0,
831 GR_RENDERBUFFER,
832 rtIDs.fMSColorRenderbufferID));
833
834 }
835 if (rtIDs.fStencilRenderbufferID) {
836 // bind the stencil to rt fbo if present, othewise the tex fbo
837 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
838 GR_STENCIL_ATTACHMENT,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000839 GR_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000840 rtIDs.fStencilRenderbufferID));
841 }
842 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
843
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000844#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000845 // On some implementations you have to be bound as DEPTH_STENCIL.
846 // (Even binding to DEPTH and STENCIL separately with the same
847 // buffer doesn't work.)
848 if (rtIDs.fStencilRenderbufferID &&
849 status != GR_FRAMEBUFFER_COMPLETE) {
850 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
851 GR_STENCIL_ATTACHMENT,
852 GR_RENDERBUFFER,
853 0));
854 GR_GLEXT(fExts,
855 FramebufferRenderbuffer(GR_FRAMEBUFFER,
856 GR_DEPTH_STENCIL_ATTACHMENT,
857 GR_RENDERBUFFER,
858 rtIDs.fStencilRenderbufferID));
859 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
860 }
861#endif
862 if (status != GR_FRAMEBUFFER_COMPLETE) {
863 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
864 status, desc.fWidth, desc.fHeight);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000865#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000866 if (rtIDs.fStencilRenderbufferID) {
867 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
868 GR_DEPTH_STENCIL_ATTACHMENT,
869 GR_RENDERBUFFER,
870 0));
871 }
872#endif
873 continue;
874 }
875 // we're successful!
876 failed = false;
877 break;
878 }
879 if (failed) {
880 if (rtIDs.fStencilRenderbufferID) {
881 GR_GLEXT(fExts,
882 DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
883 }
884 if (rtIDs.fMSColorRenderbufferID) {
885 GR_GLEXT(fExts,
886 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
887 }
888 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
889 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
890 }
891 if (rtIDs.fTexFBOID) {
892 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
893 }
894 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
895 return return_null_texture();
896 }
897 }
898#ifdef TRACE_TEXTURE_CREATION
899 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
900 tex->fTextureID, width, height, tex->fUploadByteCount);
901#endif
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000902 GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, DEFAULT_PARAMS, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000903
904 if (0 != rtIDs.fTexFBOID) {
905 GrRenderTarget* rt = tex->asRenderTarget();
906 // We've messed with FBO state but may not have set the correct viewport
907 // so just dirty the rendertarget state to force a resend.
908 fHWDrawState.fRenderTarget = NULL;
909
910 // clear the new stencil buffer if we have one
911 if (!(desc.fFlags & kNoPathRendering_TextureFlag)) {
912 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
913 fCurrDrawState.fRenderTarget = rt;
914 eraseStencil(0, ~0);
915 fCurrDrawState.fRenderTarget = rtSave;
916 }
917 }
918 return tex;
919}
920
reed@google.comac10a2d2010-12-22 21:39:39 +0000921GrVertexBuffer* GrGpuGL::createVertexBuffer(uint32_t size, bool dynamic) {
922 GLuint id;
923 GR_GL(GenBuffers(1, &id));
924 if (id) {
925 GR_GL(BindBuffer(GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000926 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000927 GrGLClearErr();
928 // make sure driver can allocate memory for this buffer
929 GR_GL_NO_ERR(BufferData(GL_ARRAY_BUFFER, size, NULL,
930 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
931 if (glGetError() != GL_NO_ERROR) {
932 GR_GL(DeleteBuffers(1, &id));
933 // deleting bound buffer does implicit bind to 0
934 fHWGeometryState.fVertexBuffer = NULL;
935 return NULL;
936 }
937 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this,
938 size, dynamic);
939 fHWGeometryState.fVertexBuffer = vertexBuffer;
940 return vertexBuffer;
941 }
942 return NULL;
943}
944
945GrIndexBuffer* GrGpuGL::createIndexBuffer(uint32_t size, bool dynamic) {
946 GLuint id;
947 GR_GL(GenBuffers(1, &id));
948 if (id) {
949 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, id));
950 GrGLClearErr();
951 // make sure driver can allocate memory for this buffer
952 GR_GL_NO_ERR(BufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL,
953 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
954 if (glGetError() != GL_NO_ERROR) {
955 GR_GL(DeleteBuffers(1, &id));
956 // deleting bound buffer does implicit bind to 0
957 fHWGeometryState.fIndexBuffer = NULL;
958 return NULL;
959 }
960 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this,
961 size, dynamic);
962 fHWGeometryState.fIndexBuffer = indexBuffer;
963 return indexBuffer;
964 }
965 return NULL;
966}
967
reed@google.comac10a2d2010-12-22 21:39:39 +0000968void GrGpuGL::flushScissor(const GrIRect* rect) {
969 GrAssert(NULL != fCurrDrawState.fRenderTarget);
970 const GrIRect& vp =
971 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
972
973 if (NULL != rect &&
974 rect->contains(vp)) {
975 rect = NULL;
976 }
977
978 if (NULL != rect) {
979 GrIRect scissor;
980 // viewport is already in GL coords
981 // create a scissor in GL coords (top > bottom)
982 scissor.setLTRB(vp.fLeft + rect->fLeft,
983 vp.fTop - rect->fTop,
984 vp.fLeft + rect->fRight,
985 vp.fTop - rect->fBottom);
986
987 if (fHWBounds.fScissorRect != scissor) {
988 GR_GL(Scissor(scissor.fLeft, scissor.fBottom,
989 scissor.width(), -scissor.height()));
990 fHWBounds.fScissorRect = scissor;
991 }
992
993 if (!fHWBounds.fScissorEnabled) {
994 GR_GL(Enable(GL_SCISSOR_TEST));
995 fHWBounds.fScissorEnabled = true;
996 }
997 } else {
998 if (fHWBounds.fScissorEnabled) {
999 GR_GL(Disable(GL_SCISSOR_TEST));
1000 fHWBounds.fScissorEnabled = false;
1001 }
1002 }
1003}
1004
reed@google.comac10a2d2010-12-22 21:39:39 +00001005void GrGpuGL::eraseColor(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001006 if (NULL == fCurrDrawState.fRenderTarget) {
1007 return;
1008 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001009 flushRenderTarget();
1010 if (fHWBounds.fScissorEnabled) {
1011 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001012 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001013 }
1014 GR_GL(ColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE));
1015 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1016 GrColorUnpackG(color)/255.f,
1017 GrColorUnpackB(color)/255.f,
1018 GrColorUnpackA(color)/255.f));
1019 GR_GL(Clear(GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001020 fWriteMaskChanged = true;
1021}
1022
1023void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001024 if (NULL == fCurrDrawState.fRenderTarget) {
1025 return;
1026 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001027 flushRenderTarget();
1028 if (fHWBounds.fScissorEnabled) {
1029 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001030 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001031 }
1032 GR_GL(StencilMask(mask));
1033 GR_GL(ClearStencil(value));
1034 GR_GL(Clear(GL_STENCIL_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001035 fWriteMaskChanged = true;
1036}
1037
1038void GrGpuGL::eraseStencilClip() {
1039 GLint stencilBitCount;
reed@google.comac20fb92011-01-12 17:14:53 +00001040 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001041 GrAssert(stencilBitCount > 0);
1042 GLint clipStencilMask = (1 << (stencilBitCount - 1));
1043 eraseStencil(0, clipStencilMask);
1044}
1045
1046void GrGpuGL::forceRenderTargetFlush() {
1047 flushRenderTarget();
1048}
1049
1050bool GrGpuGL::readPixels(int left, int top, int width, int height,
1051 GrTexture::PixelConfig config, void* buffer) {
1052 GLenum internalFormat; // we don't use this for glReadPixels
1053 GLenum format;
1054 GLenum type;
1055 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1056 return false;
1057 }
1058
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001059 if (NULL == fCurrDrawState.fRenderTarget) {
1060 return false;
1061 }
1062 flushRenderTarget();
1063
reed@google.comac10a2d2010-12-22 21:39:39 +00001064 const GrIRect& vp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1065
1066 // Brian says that viewport rects are already upside down (grrrrr)
bsalomon@google.com316f99232011-01-13 21:28:12 +00001067 GR_GL(ReadPixels(left, -vp.height() - top - height, width, height,
1068 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001069
1070 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1071 // API presents top-to-bottom
1072 {
1073 size_t stride = width * GrTexture::BytesPerPixel(config);
1074 GrAutoMalloc rowStorage(stride);
1075 void* tmp = rowStorage.get();
1076
1077 const int halfY = height >> 1;
1078 char* top = reinterpret_cast<char*>(buffer);
1079 char* bottom = top + (height - 1) * stride;
1080 for (int y = 0; y < halfY; y++) {
1081 memcpy(tmp, top, stride);
1082 memcpy(top, bottom, stride);
1083 memcpy(bottom, tmp, stride);
1084 top += stride;
1085 bottom -= stride;
1086 }
1087 }
1088 return true;
1089}
1090
1091void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001092
1093 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1094
reed@google.comac10a2d2010-12-22 21:39:39 +00001095 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1096 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
1097 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
1098 #if GR_COLLECT_STATS
1099 ++fStats.fRenderTargetChngCnt;
1100 #endif
1101 rt->setDirty(true);
1102 #if GR_DEBUG
1103 GLenum status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
1104 if (status != GR_FRAMEBUFFER_COMPLETE) {
1105 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1106 }
1107 #endif
1108 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
1109 const GrIRect& vp = rt->viewport();
1110 fRenderTargetChanged = true;
1111 if (fHWBounds.fViewportRect != vp) {
1112 GR_GL(Viewport(vp.fLeft,
1113 vp.fBottom,
1114 vp.width(),
1115 -vp.height()));
1116 fHWBounds.fViewportRect = vp;
1117 }
1118 }
1119}
1120
1121GLenum gPrimitiveType2GLMode[] = {
1122 GL_TRIANGLES,
1123 GL_TRIANGLE_STRIP,
1124 GL_TRIANGLE_FAN,
1125 GL_POINTS,
1126 GL_LINES,
1127 GL_LINE_STRIP
1128};
1129
1130void GrGpuGL::drawIndexedHelper(PrimitiveType type,
1131 uint32_t startVertex,
1132 uint32_t startIndex,
1133 uint32_t vertexCount,
1134 uint32_t indexCount) {
1135 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1136
1137 GLvoid* indices = (GLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001138
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001139 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1140 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1141
1142 // our setupGeometry better have adjusted this to zero since
1143 // DrawElements always draws from the begining of the arrays for idx 0.
1144 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001145
1146 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1147 GL_UNSIGNED_SHORT, indices));
1148}
1149
1150void GrGpuGL::drawNonIndexedHelper(PrimitiveType type,
1151 uint32_t startVertex,
1152 uint32_t vertexCount) {
1153 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1154
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001155 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1156
1157 // our setupGeometry better have adjusted this to zero.
1158 // DrawElements doesn't take an offset so we always adjus the startVertex.
1159 GrAssert(0 == startVertex);
1160
1161 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1162 // account for startVertex in the DrawElements case. So we always
1163 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001164 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1165}
1166
reed@google.comac10a2d2010-12-22 21:39:39 +00001167void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1168 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1169
1170 if (NULL != rt && rt->needsResolve()) {
1171 GrAssert(kNone_MSFBO != fMSFBOType);
1172 GrAssert(rt->textureFBOID() != rt->renderFBOID());
1173 GR_GLEXT(fExts, BindFramebuffer(GR_READ_FRAMEBUFFER,
1174 rt->renderFBOID()));
1175 GR_GLEXT(fExts, BindFramebuffer(GR_DRAW_FRAMEBUFFER,
1176 rt->textureFBOID()));
1177 #if GR_COLLECT_STATS
1178 ++fStats.fRenderTargetChngCnt;
1179 #endif
1180 // make sure we go through set render target
1181 fHWDrawState.fRenderTarget = NULL;
1182
1183 GLint left = 0;
1184 GLint right = texture->contentWidth();
1185 // we will have rendered to the top of the FBO.
1186 GLint top = texture->allocHeight();
1187 GLint bottom = texture->allocHeight() - texture->contentHeight();
1188 if (kApple_MSFBO == fMSFBOType) {
1189 GR_GL(Enable(GL_SCISSOR_TEST));
1190 GR_GL(Scissor(left, bottom, right-left, top-bottom));
1191 GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
1192 fHWBounds.fScissorRect.setEmpty();
1193 fHWBounds.fScissorEnabled = true;
1194 } else {
1195 GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
1196 left, bottom, right, top,
1197 GL_COLOR_BUFFER_BIT, GL_NEAREST));
1198 }
1199 rt->setDirty(false);
1200
1201 }
1202}
1203
1204void GrGpuGL::flushStencil() {
1205
1206 // use stencil for clipping if clipping is enabled and the clip
1207 // has been written into the stencil.
1208 bool stencilClip = fClipState.fClipInStencil &&
1209 (kClip_StateBit & fCurrDrawState.fFlagBits);
1210 bool stencilChange =
1211 fWriteMaskChanged ||
1212 fHWStencilClip != stencilClip ||
1213 fHWDrawState.fStencilPass != fCurrDrawState.fStencilPass ||
1214 (kNone_StencilPass != fCurrDrawState.fStencilPass &&
1215 (StencilPass)kSetClip_StencilPass != fCurrDrawState.fStencilPass &&
1216 fHWDrawState.fReverseFill != fCurrDrawState.fReverseFill);
1217
1218 if (stencilChange) {
1219 GLint stencilBitCount;
1220 GLint clipStencilMask;
1221 GLint pathStencilMask;
reed@google.comac20fb92011-01-12 17:14:53 +00001222 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001223 GrAssert(stencilBitCount > 0 ||
1224 kNone_StencilPass == fCurrDrawState.fStencilPass);
1225 clipStencilMask = (1 << (stencilBitCount - 1));
1226 pathStencilMask = clipStencilMask - 1;
1227 switch (fCurrDrawState.fStencilPass) {
1228 case kNone_StencilPass:
1229 if (stencilClip) {
1230 GR_GL(Enable(GL_STENCIL_TEST));
1231 GR_GL(StencilFunc(GL_EQUAL,
1232 clipStencilMask,
1233 clipStencilMask));
1234 GR_GL(StencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
1235 } else {
1236 GR_GL(Disable(GL_STENCIL_TEST));
1237 }
1238 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1239 if (!fSingleStencilPassForWinding) {
1240 GR_GL(Disable(GL_CULL_FACE));
1241 }
1242 break;
1243 case kEvenOddStencil_StencilPass:
1244 GR_GL(Enable(GL_STENCIL_TEST));
1245 if (stencilClip) {
1246 GR_GL(StencilFunc(GL_EQUAL, clipStencilMask, clipStencilMask));
1247 } else {
1248 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1249 }
1250 GR_GL(StencilMask(pathStencilMask));
1251 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1252 GR_GL(StencilOp(GL_KEEP, GL_INVERT, GL_INVERT));
1253 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1254 if (!fSingleStencilPassForWinding) {
1255 GR_GL(Disable(GL_CULL_FACE));
1256 }
1257 break;
1258 case kEvenOddColor_StencilPass: {
1259 GR_GL(Enable(GL_STENCIL_TEST));
1260 GLint funcRef = 0;
1261 GLuint funcMask = pathStencilMask;
1262 if (stencilClip) {
1263 funcRef |= clipStencilMask;
1264 funcMask |= clipStencilMask;
1265 }
1266 if (!fCurrDrawState.fReverseFill) {
1267 funcRef |= pathStencilMask;
1268 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001269
bsalomon@google.com316f99232011-01-13 21:28:12 +00001270 GR_GL(StencilFunc(GL_EQUAL, funcRef, funcMask));
1271 GR_GL(StencilMask(pathStencilMask));
reed@google.comac10a2d2010-12-22 21:39:39 +00001272 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1273 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1274 if (!fSingleStencilPassForWinding) {
1275 GR_GL(Disable(GL_CULL_FACE));
1276 }
1277 } break;
1278 case kWindingStencil1_StencilPass:
1279 GR_GL(Enable(GL_STENCIL_TEST));
1280 if (fHasStencilWrap) {
1281 if (stencilClip) {
1282 GR_GL(StencilFunc(GL_EQUAL,
1283 clipStencilMask,
1284 clipStencilMask));
1285 } else {
1286 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1287 }
1288 if (fSingleStencilPassForWinding) {
1289 GR_GL(StencilOpSeparate(GL_FRONT, GL_KEEP,
1290 GL_INCR_WRAP, GL_INCR_WRAP));
1291 GR_GL(StencilOpSeparate(GL_BACK, GL_KEEP,
1292 GL_DECR_WRAP, GL_DECR_WRAP));
1293 } else {
1294 GR_GL(StencilOp(GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP));
1295 GR_GL(Enable(GL_CULL_FACE));
1296 GR_GL(CullFace(GL_BACK));
1297 }
1298 } else {
1299 // If we don't have wrap then we use the Func to detect
1300 // values that would wrap (0 on decr and mask on incr). We
1301 // make the func fail on these values and use the sfail op
1302 // to effectively wrap by inverting.
1303 // This applies whether we are doing a two-pass (front faces
1304 // followed by back faces) or a single pass (separate func/op)
1305
1306 // Note that in the case where we are also using stencil to
1307 // clip this means we will write into the path bits in clipped
1308 // out pixels. We still apply the clip bit in the color pass
1309 // stencil func so we don't draw color outside the clip.
1310 // We also will clear the stencil bits in clipped pixels by
1311 // using zero in the sfail op with write mask set to the
1312 // path mask.
1313 GR_GL(Enable(GL_STENCIL_TEST));
1314 if (fSingleStencilPassForWinding) {
1315 GR_GL(StencilFuncSeparate(GL_FRONT,
1316 GL_NOTEQUAL,
1317 pathStencilMask,
1318 pathStencilMask));
1319 GR_GL(StencilFuncSeparate(GL_BACK,
1320 GL_NOTEQUAL,
1321 0x0,
1322 pathStencilMask));
1323 GR_GL(StencilOpSeparate(GL_FRONT, GL_INVERT,
1324 GL_INCR, GL_INCR));
1325 GR_GL(StencilOpSeparate(GL_BACK, GL_INVERT,
1326 GL_DECR, GL_DECR));
1327 } else {
1328 GR_GL(StencilFunc(GL_NOTEQUAL,
1329 pathStencilMask,
1330 pathStencilMask));
1331 GR_GL(StencilOp(GL_INVERT, GL_INCR, GL_INCR));
1332 GR_GL(Enable(GL_CULL_FACE));
1333 GR_GL(CullFace(GL_BACK));
1334 }
1335 }
1336 GR_GL(StencilMask(pathStencilMask));
1337 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1338 break;
1339 case kWindingStencil2_StencilPass:
1340 GrAssert(!fSingleStencilPassForWinding);
1341 GR_GL(Enable(GL_STENCIL_TEST));
1342 if (fHasStencilWrap) {
1343 if (stencilClip) {
1344 GR_GL(StencilFunc(GL_EQUAL,
1345 clipStencilMask,
1346 clipStencilMask));
1347 } else {
1348 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1349 }
1350 GR_GL(StencilOp(GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP));
1351 } else {
1352 GR_GL(StencilFunc(GL_NOTEQUAL, 0x0, pathStencilMask));
1353 GR_GL(StencilOp(GL_INVERT, GL_DECR, GL_DECR));
1354 }
1355 GR_GL(StencilMask(pathStencilMask));
1356 GR_GL(Enable(GL_CULL_FACE));
1357 GR_GL(CullFace(GL_FRONT));
1358 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1359 break;
1360 case kWindingColor_StencilPass: {
1361 GR_GL(Enable(GL_STENCIL_TEST));
1362 GLint funcRef = 0;
1363 GLuint funcMask = pathStencilMask;
1364 GLenum funcFunc;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001365
reed@google.comac10a2d2010-12-22 21:39:39 +00001366 if (stencilClip) {
1367 funcRef |= clipStencilMask;
1368 funcMask |= clipStencilMask;
1369 }
1370 if (fCurrDrawState.fReverseFill) {
1371 funcFunc = GL_EQUAL;
1372 } else {
1373 funcFunc = GL_LESS;
1374 }
1375 GR_GL(StencilFunc(funcFunc, funcRef, funcMask));
1376 GR_GL(StencilMask(pathStencilMask));
1377 // must zero in sfail because winding w/o wrap will write
1378 // path stencil bits in clipped out pixels
1379 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1380 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1381 if (!fSingleStencilPassForWinding) {
1382 GR_GL(Disable(GL_CULL_FACE));
1383 }
1384 } break;
1385 case kSetClip_StencilPass:
1386 GR_GL(Enable(GL_STENCIL_TEST));
1387 GR_GL(StencilFunc(GL_ALWAYS, clipStencilMask, clipStencilMask));
1388 GR_GL(StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
1389 GR_GL(StencilMask(clipStencilMask));
1390 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1391 if (!fSingleStencilPassForWinding) {
1392 GR_GL(Disable(GL_CULL_FACE));
1393 }
1394 break;
1395 default:
1396 GrAssert(!"Unexpected stencil pass.");
1397 break;
1398
1399 }
1400 fHWDrawState.fStencilPass = fCurrDrawState.fStencilPass;
1401 fHWDrawState.fReverseFill = fCurrDrawState.fReverseFill;
1402 fWriteMaskChanged = false;
1403 fHWStencilClip = stencilClip;
1404 }
1405}
1406
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001407bool GrGpuGL::flushGLStateCommon(PrimitiveType type) {
1408
1409 // GrGpu::setupClipAndFlushState should have already checked this
1410 // and bailed if not true.
1411 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001412
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001413 for (int s = 0; s < kNumStages; ++s) {
1414 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001415
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001416 // bind texture and set sampler state
1417 if (usingTexture) {
1418 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001419
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001420 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001421 // if we created a rt/tex and rendered to it without using a
1422 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001423 // the last bound texture, but it needs resolving. So keep this
1424 // out of the "last != next" check.
1425 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001426
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001427 if (fHWDrawState.fTextures[s] != nextTexture) {
1428 setTextureUnit(s);
1429 GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
1430 #if GR_COLLECT_STATS
1431 ++fStats.fTextureChngCnt;
1432 #endif
1433 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1434 fHWDrawState.fTextures[s] = nextTexture;
1435 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001436
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001437 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001438 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001439 nextTexture->getTexParams();
1440 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001441
1442 newTexParams.fFilter = sampler.isFilter() ? GL_LINEAR :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001443 GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001444 newTexParams.fWrapS =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001445 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001446 newTexParams.fWrapT =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001447 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001448
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001449 if (newTexParams.fFilter != oldTexParams.fFilter) {
1450 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001451 GR_GL(TexParameteri(GL_TEXTURE_2D,
1452 GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001453 newTexParams.fFilter));
bsalomon@google.com316f99232011-01-13 21:28:12 +00001454 GR_GL(TexParameteri(GL_TEXTURE_2D,
1455 GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001456 newTexParams.fFilter));
1457 }
1458 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1459 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001460 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001461 GL_TEXTURE_WRAP_S,
1462 newTexParams.fWrapS));
1463 }
1464 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1465 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001466 GR_GL(TexParameteri(GL_TEXTURE_2D,
1467 GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001468 newTexParams.fWrapT));
1469 }
1470 nextTexture->setTexParams(newTexParams);
1471 } else {
1472 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001473 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001474 }
1475 }
1476 }
1477
1478 flushRenderTarget();
1479
1480 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1481 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1482 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
1483 GR_GL(Enable(GL_DITHER));
1484 } else {
1485 GR_GL(Disable(GL_DITHER));
1486 }
1487 }
1488
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001489#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +00001490 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1491 // smooth lines.
1492 if (fRenderTargetChanged ||
1493 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1494 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1495 GLint msaa = 0;
1496 // only perform query if we know MSAA is supported.
1497 // calling on non-MSAA target caused a crash in one environment,
1498 // though I don't think it should.
1499 if (!fAASamples[kHigh_AALevel]) {
reed@google.comac20fb92011-01-12 17:14:53 +00001500 GR_GL_GetIntegerv(GL_SAMPLE_BUFFERS, &msaa);
reed@google.comac10a2d2010-12-22 21:39:39 +00001501 }
1502 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1503 if (msaa) {
1504 GR_GL(Enable(GL_MULTISAMPLE));
1505 } else {
1506 GR_GL(Enable(GL_LINE_SMOOTH));
1507 }
1508 } else {
1509 if (msaa) {
1510 GR_GL(Disable(GL_MULTISAMPLE));
1511 }
1512 GR_GL(Disable(GL_LINE_SMOOTH));
1513 }
1514 }
1515#endif
1516
1517 bool blendOff = canDisableBlend();
1518 if (fHWBlendDisabled != blendOff) {
1519 if (blendOff) {
1520 GR_GL(Disable(GL_BLEND));
1521 } else {
1522 GR_GL(Enable(GL_BLEND));
1523 }
1524 fHWBlendDisabled = blendOff;
1525 }
1526
1527 if (!blendOff) {
1528 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1529 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1530 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1531 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1532 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1533 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1534 }
1535 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001536
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001537#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001538 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001539 for (int s = 0; s < kNumStages; ++s) {
1540 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1541 NULL == fCurrDrawState.fRenderTarget ||
1542 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001543 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001544 fCurrDrawState.fRenderTarget);
1545 }
1546#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001547
reed@google.comac10a2d2010-12-22 21:39:39 +00001548 flushStencil();
1549
1550 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001551 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001552}
1553
1554void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001555 if (fHWGeometryState.fVertexBuffer != buffer) {
1556 fHWGeometryState.fArrayPtrsDirty = true;
1557 fHWGeometryState.fVertexBuffer = buffer;
1558 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001559}
1560
1561void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1562 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1563 buffer == fGeometrySrc.fVertexBuffer));
1564
1565 if (fHWGeometryState.fVertexBuffer == buffer) {
1566 // deleting bound buffer does implied bind to 0
1567 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001568 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001569 }
1570}
1571
1572void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1573 fGeometrySrc.fIndexBuffer = buffer;
1574}
1575
1576void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1577 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1578 buffer == fGeometrySrc.fIndexBuffer));
1579
1580 if (fHWGeometryState.fIndexBuffer == buffer) {
1581 // deleting bound buffer does implied bind to 0
1582 fHWGeometryState.fIndexBuffer = NULL;
1583 }
1584}
1585
reed@google.comac10a2d2010-12-22 21:39:39 +00001586void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1587 GrAssert(NULL != renderTarget);
1588
1589 // if the bound FBO is destroyed we can't rely on the implicit bind to 0
1590 // a) we want the default RT which may not be FBO 0
1591 // b) we set more state than just FBO based on the RT
1592 // So trash the HW state to force an RT flush next time
1593 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001594 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001595 }
1596 if (fHWDrawState.fRenderTarget == renderTarget) {
1597 fHWDrawState.fRenderTarget = NULL;
1598 }
1599 if (fClipState.fStencilClipTarget == renderTarget) {
1600 fClipState.fStencilClipTarget = NULL;
1601 }
1602}
1603
1604void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001605 for (int s = 0; s < kNumStages; ++s) {
1606 if (fCurrDrawState.fTextures[s] == texture) {
1607 fCurrDrawState.fTextures[s] = NULL;
1608 }
1609 if (fHWDrawState.fTextures[s] == texture) {
1610 // deleting bound texture does implied bind to 0
1611 fHWDrawState.fTextures[s] = NULL;
1612 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001613 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001614}
1615
1616void GrGpuGL::notifyTextureRemoveRenderTarget(GrGLTexture* texture) {
1617 GrAssert(NULL != texture->asRenderTarget());
1618
1619 // if there is a pending resolve, perform it.
1620 resolveTextureRenderTarget(texture);
1621}
1622
1623bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
1624 GLenum* internalFormat,
1625 GLenum* format,
1626 GLenum* type) {
1627 switch (config) {
1628 case GrTexture::kRGBA_8888_PixelConfig:
1629 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001630 *format = GR_GL_32BPP_COLOR_FORMAT;
reed@google.com63100f92011-01-18 21:32:14 +00001631#if GR_SUPPORT_GLES
1632 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1633 // format for a BGRA is BGRA not RGBA (as on desktop)
1634 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1635#else
1636 *internalFormat = GL_RGBA;
bsalomon@google.comed3a0682011-01-18 16:54:04 +00001637#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001638 *type = GL_UNSIGNED_BYTE;
1639 break;
1640 case GrTexture::kRGB_565_PixelConfig:
1641 *format = GL_RGB;
1642 *internalFormat = GL_RGB;
1643 *type = GL_UNSIGNED_SHORT_5_6_5;
1644 break;
1645 case GrTexture::kRGBA_4444_PixelConfig:
1646 *format = GL_RGBA;
1647 *internalFormat = GL_RGBA;
1648 *type = GL_UNSIGNED_SHORT_4_4_4_4;
1649 break;
1650 case GrTexture::kIndex_8_PixelConfig:
1651 if (this->supports8BitPalette()) {
1652 *format = GR_PALETTE8_RGBA8;
1653 *internalFormat = GR_PALETTE8_RGBA8;
1654 *type = GL_UNSIGNED_BYTE; // unused I think
1655 } else {
1656 return false;
1657 }
1658 break;
1659 case GrTexture::kAlpha_8_PixelConfig:
1660 *format = GL_ALPHA;
1661 *internalFormat = GL_ALPHA;
1662 *type = GL_UNSIGNED_BYTE;
1663 break;
1664 default:
1665 return false;
1666 }
1667 return true;
1668}
1669
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001670void GrGpuGL::setTextureUnit(int unit) {
1671 GrAssert(unit >= 0 && unit < kNumStages);
1672 if (fActiveTextureUnitIdx != unit) {
1673 GR_GL(ActiveTexture(GL_TEXTURE0 + unit));
1674 fActiveTextureUnitIdx = unit;
1675 }
1676}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001677
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001678void GrGpuGL::setSpareTextureUnit() {
1679 if (fActiveTextureUnitIdx != (GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1680 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
1681 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1682 }
1683}
1684
reed@google.comac10a2d2010-12-22 21:39:39 +00001685/* On ES the internalFormat and format must match for TexImage and we use
1686 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1687 decide the internalFormat. However, on ES internalFormat for
1688 RenderBufferStorage* has to be a specific format (not a base format like
1689 GL_RGBA).
1690 */
1691bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) {
1692 switch (config) {
1693 case GrTexture::kRGBA_8888_PixelConfig:
1694 case GrTexture::kRGBX_8888_PixelConfig:
1695 if (fRGBA8Renderbuffer) {
1696 *format = GR_RGBA8;
1697 return true;
1698 } else {
1699 return false;
1700 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001701#if GR_SUPPORT_GLES // ES2 supports 565. ES1 supports it with FBO extension
1702 // desktop GL has no such internal format
reed@google.comac10a2d2010-12-22 21:39:39 +00001703 case GrTexture::kRGB_565_PixelConfig:
1704 *format = GR_RGB565;
1705 return true;
1706#endif
1707 case GrTexture::kRGBA_4444_PixelConfig:
1708 *format = GL_RGBA4;
1709 return true;
1710 default:
1711 return false;
1712 }
1713}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001714
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001715void GrGpuGL::setBuffers(bool indexed,
1716 int* extraVertexOffset,
1717 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001718
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001719 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001720
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001721 GrGLVertexBuffer* vbuf;
1722 switch (fGeometrySrc.fVertexSrc) {
1723 case kBuffer_GeometrySrcType:
1724 *extraVertexOffset = 0;
1725 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1726 break;
1727 case kArray_GeometrySrcType:
1728 case kReserved_GeometrySrcType:
1729 finalizeReservedVertices();
1730 *extraVertexOffset = fCurrPoolStartVertex;
1731 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1732 break;
1733 default:
1734 vbuf = NULL; // suppress warning
1735 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001736 }
1737
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001738 GrAssert(NULL != vbuf);
1739 GrAssert(!vbuf->isLocked());
1740 if (fHWGeometryState.fVertexBuffer != vbuf) {
1741 GR_GL(BindBuffer(GL_ARRAY_BUFFER, vbuf->bufferID()));
1742 fHWGeometryState.fArrayPtrsDirty = true;
1743 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001744 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001745
1746 if (indexed) {
1747 GrAssert(NULL != extraIndexOffset);
1748
1749 GrGLIndexBuffer* ibuf;
1750 switch (fGeometrySrc.fIndexSrc) {
1751 case kBuffer_GeometrySrcType:
1752 *extraIndexOffset = 0;
1753 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1754 break;
1755 case kArray_GeometrySrcType:
1756 case kReserved_GeometrySrcType:
1757 finalizeReservedIndices();
1758 *extraIndexOffset = fCurrPoolStartIndex;
1759 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1760 break;
1761 default:
1762 ibuf = NULL; // suppress warning
1763 GrCrash("Unknown geometry src type!");
1764 }
1765
1766 GrAssert(NULL != ibuf);
1767 GrAssert(!ibuf->isLocked());
1768 if (fHWGeometryState.fIndexBuffer != ibuf) {
1769 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
1770 fHWGeometryState.fIndexBuffer = ibuf;
1771 }
1772 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001773}