blob: d366953d86f06d62baf634468a5b52fd40365836 [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
reed@google.comac10a2d2010-12-22 21:39:39 +000051
reed@google.comac10a2d2010-12-22 21:39:39 +000052///////////////////////////////////////////////////////////////////////////////
53
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +000054static bool gPrintStartupSpew;
55
56
reed@google.comac10a2d2010-12-22 21:39:39 +000057bool fbo_test(GrGLExts exts, int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000058
59 GLint savedFBO;
60 GLint savedTexUnit;
reed@google.com3d8de042011-01-20 02:18:00 +000061 GR_GL_GetIntegerv(GL_ACTIVE_TEXTURE, &savedTexUnit);
62 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +000063
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000064 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +000065
reed@google.comac10a2d2010-12-22 21:39:39 +000066 GLuint testFBO;
67 GR_GLEXT(exts, GenFramebuffers(1, &testFBO));
68 GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, testFBO));
69 GLuint testRTTex;
70 GR_GL(GenTextures(1, &testRTTex));
71 GR_GL(BindTexture(GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +000072 // some implementations require texture to be mip-map complete before
73 // FBO with level 0 bound as color attachment will be framebuffer complete.
74 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +000075 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h,
76 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
77 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
78 GR_GLEXT(exts, FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0,
79 GL_TEXTURE_2D, testRTTex, 0));
80 GLenum status = GR_GLEXT(exts, CheckFramebufferStatus(GR_FRAMEBUFFER));
81 GR_GLEXT(exts, DeleteFramebuffers(1, &testFBO));
82 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +000083
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000084 GR_GL(ActiveTexture(savedTexUnit));
85 GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +000086
reed@google.comac10a2d2010-12-22 21:39:39 +000087 return status == GR_FRAMEBUFFER_COMPLETE;
88}
89
reed@google.comac10a2d2010-12-22 21:39:39 +000090GrGpuGL::GrGpuGL() {
reed@google.comeeeb5a02010-12-23 15:12:59 +000091 if (gPrintStartupSpew) {
92 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
93 this);
94 GrPrintf("------ VENDOR %s\n", glGetString(GL_VENDOR));
95 GrPrintf("------ RENDERER %s\n", glGetString(GL_RENDERER));
96 GrPrintf("------ VERSION %s\n", glGetString(GL_VERSION));
97 GrPrintf("------ EXTENSIONS\n %s \n", glGetString(GL_EXTENSIONS));
98 }
reed@google.comac10a2d2010-12-22 21:39:39 +000099
100 GrGLClearErr();
101
102 GrGLInitExtensions(&fExts);
103
104 resetContextHelper();
105
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000106 fHWDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000107 fRenderTargetChanged = true;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000108
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000109 GLint maxTextureUnits;
110 // check FS and fixed-function texture unit limits
111 // we only use textures in the fragment stage currently.
112 // checks are > to make sure we have a spare unit.
113#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES2
reed@google.com3d8de042011-01-20 02:18:00 +0000114 GR_GL_GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000115 GrAssert(maxTextureUnits > kNumStages);
116#endif
117#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1
reed@google.com3d8de042011-01-20 02:18:00 +0000118 GR_GL_GetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000119 GrAssert(maxTextureUnits > kNumStages);
120#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +0000121
reed@google.comac10a2d2010-12-22 21:39:39 +0000122 fCurrDrawState = fHWDrawState;
123
124 ////////////////////////////////////////////////////////////////////////////
125 // Check for supported features.
126
127 int major, minor;
128 gl_version(&major, &minor);
129
130 GLint numFormats;
reed@google.comac20fb92011-01-12 17:14:53 +0000131 GR_GL_GetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000132 GrAutoSTMalloc<10, GLint> formats(numFormats);
reed@google.comac20fb92011-01-12 17:14:53 +0000133 GR_GL_GetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000134 for (int i = 0; i < numFormats; ++i) {
135 if (formats[i] == GR_PALETTE8_RGBA8) {
136 f8bitPaletteSupport = true;
137 break;
138 }
139 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000140
141 if (gPrintStartupSpew) {
142 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
143 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000144
145 GR_STATIC_ASSERT(0 == kNone_AALevel);
146 GR_STATIC_ASSERT(1 == kLow_AALevel);
147 GR_STATIC_ASSERT(2 == kMed_AALevel);
148 GR_STATIC_ASSERT(3 == kHigh_AALevel);
149
150 memset(fAASamples, 0, sizeof(fAASamples));
151 fMSFBOType = kNone_MSFBO;
152 if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
153 fMSFBOType = kIMG_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000154 if (gPrintStartupSpew) {
155 GrPrintf("MSAA Support: IMG ES EXT.\n");
156 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000157 }
158 else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
159 fMSFBOType = kApple_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000160 if (gPrintStartupSpew) {
161 GrPrintf("MSAA Support: APPLE ES EXT.\n");
162 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000163 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000164#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 else if ((major >= 3) ||
166 has_gl_extension("GL_ARB_framebuffer_object") ||
167 (has_gl_extension("GL_EXT_framebuffer_multisample") &&
168 has_gl_extension("GL_EXT_framebuffer_blit"))) {
169 fMSFBOType = kDesktop_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000170 if (gPrintStartupSpew) {
171 GrPrintf("MSAA Support: DESKTOP\n");
172 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000173 }
174#endif
175 else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000176 if (gPrintStartupSpew) {
177 GrPrintf("MSAA Support: NONE\n");
178 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000179 }
180
181 if (kNone_MSFBO != fMSFBOType) {
182 GLint maxSamples;
183 GLenum maxSampleGetter = (kIMG_MSFBO == fMSFBOType) ?
184 GR_MAX_SAMPLES_IMG :
185 GR_MAX_SAMPLES;
reed@google.comac20fb92011-01-12 17:14:53 +0000186 GR_GL_GetIntegerv(maxSampleGetter, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000187 if (maxSamples > 1 ) {
188 fAASamples[kNone_AALevel] = 0;
189 fAASamples[kLow_AALevel] = GrMax(2,
190 GrFixedFloorToInt((GR_FixedHalf) *
191 maxSamples));
192 fAASamples[kMed_AALevel] = GrMax(2,
193 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
194 maxSamples));
195 fAASamples[kHigh_AALevel] = maxSamples;
196 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000197 if (gPrintStartupSpew) {
198 GrPrintf("\tMax Samples: %d\n", maxSamples);
199 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000200 }
201
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000202#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000203 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
204 has_gl_extension("GL_EXT_stencil_wrap");
205#else
206 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
207#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000208 if (gPrintStartupSpew) {
209 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
210 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000211
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000212#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000213 // we could also look for GL_ATI_separate_stencil extension or
214 // GL_EXT_stencil_two_side but they use different function signatures
215 // than GL2.0+ (and than each other).
216 fSingleStencilPassForWinding = (major >= 2);
217#else
218 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
219 // an ES1 extension.
220 fSingleStencilPassForWinding = (major >= 2);
221#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000222 if (gPrintStartupSpew) {
223 GrPrintf("Single Stencil Pass For Winding: %s\n", (fSingleStencilPassForWinding ? "YES" : "NO"));
224 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000225
226
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000227#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000228 fRGBA8Renderbuffer = true;
229#else
230 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
231#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000232 if (gPrintStartupSpew) {
233 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
234 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000235
bsalomon@google.comed3a0682011-01-18 16:54:04 +0000236#if GR_SUPPORT_GLES
237 if (GR_GL_32BPP_COLOR_FORMAT == GR_BGRA) {
238 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
239 }
240#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000241
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000242#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000243 fBufferLockSupport = true; // we require VBO support and the desktop VBO
244 // extension includes glMapBuffer.
245#else
246 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
247#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000248 if (gPrintStartupSpew) {
249 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
250 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000251
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000252#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com0748f212011-02-01 22:56:16 +0000253 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
254 fNPOTTextureTileSupport = true;
255 fNPOTTextureSupport = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000256 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000257 fNPOTTextureTileSupport = false;
258 fNPOTTextureSupport = false;
259 }
260#else
261 if (major >= 2) {
262 fNPOTTextureSupport = true;
263 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
264 } else {
265 fNPOTTextureSupport = has_gl_extension("GL_APPLE_texture_2D_limited_npot");
266 fNPOTTextureTileSupport = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000267 }
268#endif
269 ////////////////////////////////////////////////////////////////////////////
270 // Experiments to determine limitations that can't be queried. TODO: Make
271 // these a preprocess that generate some compile time constants.
272
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000273 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000274
bsalomon@google.com0748f212011-02-01 22:56:16 +0000275 bool simpleFBOSuccess = fbo_test(fExts, 128, 128);
276 if (gPrintStartupSpew) {
277 if (!simpleFBOSuccess) {
278 GrPrintf("FBO Sanity Test: FAILED\n");
279 } else {
280 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000281 }
282 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000283 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000284
reed@google.comac10a2d2010-12-22 21:39:39 +0000285 /* Experimentation has found that some GLs that support NPOT textures
286 do not support FBOs with a NPOT texture. They report "unsupported" FBO
287 status. I don't know how to explicitly query for this. Do an
288 experiment. Note they may support NPOT with a renderbuffer but not a
289 texture. Presumably, the implementation bloats the renderbuffer
290 internally to the next POT.
291 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000292 bool fNPOTRenderTargetSupport = false;
293 if (fNPOTTextureSupport) {
294 fNPOTRenderTargetSupport = fbo_test(fExts, 200, 200);
295 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000296
bsalomon@google.com0748f212011-02-01 22:56:16 +0000297 if (gPrintStartupSpew) {
298 if (fNPOTTextureSupport) {
299 GrPrintf("NPOT textures supported\n");
300 if (fNPOTTextureTileSupport) {
301 GrPrintf("NPOT texture tiling supported\n");
302 } else {
303 GrPrintf("NPOT texture tiling NOT supported\n");
304 }
305 if (fNPOTRenderTargetSupport) {
306 GrPrintf("NPOT render targets supported\n");
307 } else {
308 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000309 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000310 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000311 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000312 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000313 }
314
reed@google.comac10a2d2010-12-22 21:39:39 +0000315 /* The iPhone 4 has a restriction that for an FBO with texture color
316 attachment with height <= 8 then the width must be <= height. Here
317 we look for such a limitation.
318 */
319 fMinRenderTargetHeight = GR_INVAL_GLINT;
320 GLint maxRenderSize;
reed@google.comac20fb92011-01-12 17:14:53 +0000321 GR_GL_GetIntegerv(GR_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000322
reed@google.comeeeb5a02010-12-23 15:12:59 +0000323 if (gPrintStartupSpew) {
324 GrPrintf("Small height FBO texture experiments\n");
325 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000326
327 for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000328 GLuint w = maxRenderSize;
329 GLuint h = i;
330 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000331 if (gPrintStartupSpew) {
332 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
333 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000334 fMinRenderTargetHeight = i;
335 break;
336 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000337 if (gPrintStartupSpew) {
338 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
339 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000340 }
341 }
342 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
343
reed@google.comeeeb5a02010-12-23 15:12:59 +0000344 if (gPrintStartupSpew) {
345 GrPrintf("Small width FBO texture experiments\n");
346 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000347 fMinRenderTargetWidth = GR_MAX_GLUINT;
bsalomon@google.com0748f212011-02-01 22:56:16 +0000348 for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000349 GLuint w = i;
350 GLuint h = maxRenderSize;
351 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000352 if (gPrintStartupSpew) {
353 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
354 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000355 fMinRenderTargetWidth = i;
356 break;
357 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000358 if (gPrintStartupSpew) {
359 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
360 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000361 }
362 }
363 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
364
reed@google.com02a7e6c2011-01-28 21:21:49 +0000365 GR_GL_GetIntegerv(GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000366}
367
368GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000369}
370
371void GrGpuGL::resetContextHelper() {
372// We detect cases when blending is effectively off
373 fHWBlendDisabled = false;
374 GR_GL(Enable(GL_BLEND));
375
376 // this is always disabled
377 GR_GL(Disable(GL_CULL_FACE));
378
379 GR_GL(Disable(GL_DITHER));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000380#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000381 GR_GL(Disable(GL_LINE_SMOOTH));
382 GR_GL(Disable(GL_POINT_SMOOTH));
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000383 GR_GL(Disable(GL_MULTISAMPLE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000384#endif
385
386 // we only ever use lines in hairline mode
387 GR_GL(LineWidth(1));
388
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000389 // invalid
390 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000391
392 fHWDrawState.fFlagBits = 0;
393
394 // illegal values
395 fHWDrawState.fSrcBlend = (BlendCoeff)-1;
396 fHWDrawState.fDstBlend = (BlendCoeff)-1;
397 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000398
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000399 fHWDrawState.fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax); // illegal
bsalomon@google.com316f99232011-01-13 21:28:12 +0000400
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000401 for (int s = 0; s < kNumStages; ++s) {
402 fHWDrawState.fTextures[s] = NULL;
403 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
404 -GR_ScalarMax,
405 true);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000406 fHWDrawState.fTextureMatrices[s].setScale(GR_ScalarMax, GR_ScalarMax);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000407 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000408
reed@google.comac10a2d2010-12-22 21:39:39 +0000409 GR_GL(Scissor(0,0,0,0));
410 fHWBounds.fScissorRect.setLTRB(0,0,0,0);
411 fHWBounds.fScissorEnabled = false;
412 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000413 fHWBounds.fViewportRect.setLTRB(-1,-1,-1,-1);
reed@google.comac10a2d2010-12-22 21:39:39 +0000414
reed@google.comac10a2d2010-12-22 21:39:39 +0000415 // disabling the stencil test also disables
416 // stencil buffer writes
417 GR_GL(Disable(GL_STENCIL_TEST));
418 GR_GL(StencilMask(0xffffffff));
419 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
420 fHWDrawState.fReverseFill = false;
421 fHWDrawState.fStencilPass = kNone_StencilPass;
422 fHWStencilClip = false;
423
424 fHWGeometryState.fIndexBuffer = NULL;
425 fHWGeometryState.fVertexBuffer = NULL;
426 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
427 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
428
429 fHWDrawState.fRenderTarget = NULL;
430}
431
432void GrGpuGL::resetContext() {
433 INHERITED::resetContext();
434 resetContextHelper();
435}
436
reed@google.comac10a2d2010-12-22 21:39:39 +0000437GrRenderTarget* GrGpuGL::createPlatformRenderTarget(
438 intptr_t platformRenderTarget,
439 int width, int height) {
440 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
441 rtIDs.fStencilRenderbufferID = 0;
442 rtIDs.fMSColorRenderbufferID = 0;
443 rtIDs.fTexFBOID = 0;
444 rtIDs.fOwnIDs = false;
445
446 GrIRect viewport;
447
448 // viewport is in GL coords (top >= bottom)
449 viewport.setLTRB(0, height, width, 0);
450
451 rtIDs.fRTFBOID = (GLuint)platformRenderTarget;
452 rtIDs.fTexFBOID = (GLuint)platformRenderTarget;
453
454 GrGLRenderTarget* rt = new GrGLRenderTarget(rtIDs, viewport, NULL, this);
455
456 return rt;
457}
458
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000459GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000460
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000461 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000462
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000463 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&rtIDs.fRTFBOID);
464 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
465 rtIDs.fMSColorRenderbufferID = 0;
466 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000467
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000468 GLint vp[4];
469 GR_GL_GetIntegerv(GL_VIEWPORT, vp);
470 GrIRect viewportRect;
471 viewportRect.setLTRB(vp[0],
472 vp[1] + vp[3],
473 vp[0] + vp[2],
474 vp[1]);
475 rtIDs.fOwnIDs = false;
476
477 return new GrGLRenderTarget(rtIDs,
478 viewportRect,
479 NULL,
480 this);
481}
482
bsalomon@google.com5782d712011-01-21 21:03:59 +0000483///////////////////////////////////////////////////////////////////////////////
484
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000485// defines stencil formats from more to less preferred
reed@google.com63100f92011-01-18 21:32:14 +0000486GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = {
487 GR_STENCIL_INDEX8,
488
489#if GR_SUPPORT_GLDESKTOP
490 GR_STENCIL_INDEX16,
491#endif
492
493 GR_DEPTH24_STENCIL8,
494 GR_STENCIL_INDEX4,
495
496#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000497 GL_STENCIL_INDEX,
498 GR_DEPTH_STENCIL,
499#endif
500};
501
502// good to set a break-point here to know when createTexture fails
503static GrTexture* return_null_texture() {
504// GrAssert(!"null texture");
505 return NULL;
506}
507
508#if GR_DEBUG
509static size_t as_size_t(int x) {
510 return x;
511}
512#endif
513
reed@google.comac10a2d2010-12-22 21:39:39 +0000514GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
515 const void* srcData, size_t rowBytes) {
516
517#if GR_COLLECT_STATS
518 ++fStats.fTextureCreateCnt;
519#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000520
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000521 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000522
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000523 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
524 GL_NEAREST,
525 GL_CLAMP_TO_EDGE,
526 GL_CLAMP_TO_EDGE
527 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000528
reed@google.comac10a2d2010-12-22 21:39:39 +0000529 GrGLTexture::GLTextureDesc glDesc;
530 GLenum internalFormat;
531
532 glDesc.fContentWidth = desc.fWidth;
533 glDesc.fContentHeight = desc.fHeight;
534 glDesc.fAllocWidth = desc.fWidth;
535 glDesc.fAllocHeight = desc.fHeight;
536 glDesc.fFormat = desc.fFormat;
537
538 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
539 if (!canBeTexture(desc.fFormat,
540 &internalFormat,
541 &glDesc.fUploadFormat,
542 &glDesc.fUploadType)) {
543 return return_null_texture();
544 }
545
546 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
547 GLint samples = fAASamples[desc.fAALevel];
548 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
549 GrPrintf("AA RT requested but not supported on this platform.");
550 }
551
552 GR_GL(GenTextures(1, &glDesc.fTextureID));
553 if (!glDesc.fTextureID) {
554 return return_null_texture();
555 }
556
557 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
558
559 /*
560 * check if our srcData has extra bytes past each row. If so, we need
561 * to trim those off here, since GL doesn't let us pass the rowBytes as
562 * a parameter to glTexImage2D
563 */
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000564#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000565 if (srcData) {
566 GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH,
567 rowBytes / glDesc.fUploadByteCount));
568 }
569#else
570 GrAutoSMalloc<128 * 128> trimStorage;
571 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
572 if (srcData && (trimRowBytes < rowBytes)) {
573 size_t trimSize = desc.fHeight * trimRowBytes;
574 trimStorage.realloc(trimSize);
575 // now copy the data into our new storage, skipping the trailing bytes
576 const char* src = (const char*)srcData;
577 char* dst = (char*)trimStorage.get();
578 for (uint32_t y = 0; y < desc.fHeight; y++) {
579 memcpy(dst, src, trimRowBytes);
580 src += rowBytes;
581 dst += trimRowBytes;
582 }
583 // now point srcData to our trimmed version
584 srcData = trimStorage.get();
585 }
586#endif
587
reed@google.comac10a2d2010-12-22 21:39:39 +0000588 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000589 if (!this->npotRenderTargetSupport()) {
590 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
591 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
592 }
593
reed@google.comac10a2d2010-12-22 21:39:39 +0000594 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
595 glDesc.fAllocWidth);
596 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
597 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000598 } else if (!this->npotTextureSupport()) {
599 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
600 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000601 }
602
603 GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000604 GR_GL(TexParameteri(GL_TEXTURE_2D,
605 GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000606 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000607 GR_GL(TexParameteri(GL_TEXTURE_2D,
608 GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000609 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000610 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000611 GL_TEXTURE_WRAP_S,
612 DEFAULT_PARAMS.fWrapS));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000613 GR_GL(TexParameteri(GL_TEXTURE_2D,
614 GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000615 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000616
617 GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
618 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
619 supports8BitPalette()) {
620 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
621 GrAssert(desc.fWidth == glDesc.fAllocWidth);
622 GrAssert(desc.fHeight == glDesc.fAllocHeight);
623 GLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
624 kColorTableSize;
625 GR_GL(CompressedTexImage2D(GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
626 glDesc.fAllocWidth, glDesc.fAllocHeight,
627 0, imageSize, srcData));
628 GrGL_RestoreResetRowLength();
629 } else {
630 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
631 glDesc.fAllocHeight != desc.fHeight)) {
632 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat,
633 glDesc.fAllocWidth, glDesc.fAllocHeight,
634 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
635 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
636 desc.fHeight, glDesc.fUploadFormat,
637 glDesc.fUploadType, srcData));
638 GrGL_RestoreResetRowLength();
639
640 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
641 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
642 uint32_t maxTexels = extraW * extraH;
643 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
644 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
645
646 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
647
648 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
649 if (extraH) {
650 uint8_t* lastRowStart = (uint8_t*) srcData +
651 (desc.fHeight - 1) * rowSize;
652 uint8_t* extraRowStart = (uint8_t*)texels.get();
653
654 for (uint32_t i = 0; i < extraH; ++i) {
655 memcpy(extraRowStart, lastRowStart, rowSize);
656 extraRowStart += rowSize;
657 }
658 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
659 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
660 texels.get()));
661 }
662 if (extraW) {
663 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
664 uint8_t* extraTexel = (uint8_t*)texels.get();
665 for (uint32_t j = 0; j < desc.fHeight; ++j) {
666 for (uint32_t i = 0; i < extraW; ++i) {
667 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
668 extraTexel += glDesc.fUploadByteCount;
669 }
670 edgeTexel += rowSize;
671 }
672 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
673 desc.fHeight, glDesc.fUploadFormat,
674 glDesc.fUploadType, texels.get()));
675 }
676 if (extraW && extraH) {
677 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
678 - glDesc.fUploadByteCount;
679 uint8_t* extraTexel = (uint8_t*)texels.get();
680 for (uint32_t i = 0; i < extraW*extraH; ++i) {
681 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
682 extraTexel += glDesc.fUploadByteCount;
683 }
684 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
685 extraW, extraH, glDesc.fUploadFormat,
686 glDesc.fUploadType, texels.get()));
687 }
688
689 } else {
690 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
691 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
692 glDesc.fUploadType, srcData));
693 GrGL_RestoreResetRowLength();
694 }
695 }
696
697 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
698
699 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
700 rtIDs.fStencilRenderbufferID = 0;
701 rtIDs.fMSColorRenderbufferID = 0;
702 rtIDs.fRTFBOID = 0;
703 rtIDs.fTexFBOID = 0;
704 rtIDs.fOwnIDs = true;
705 GLenum msColorRenderbufferFormat = -1;
706
707 if (renderTarget) {
708#if GR_COLLECT_STATS
709 ++fStats.fRenderTargetCreateCnt;
710#endif
711 bool failed = true;
712 GLenum status;
713 GLint err;
714
715 // If need have both RT flag and srcData we have
716 // to invert the data before uploading because FBO
717 // will be rendered bottom up
718 GrAssert(NULL == srcData);
719 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
720
721 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fTexFBOID));
722 GrAssert(rtIDs.fTexFBOID);
723
724 // If we are using multisampling and any extension other than the IMG
725 // one we will create two FBOs. We render to one and then resolve to
726 // the texture bound to the other. The IMG extension does an implicit
727 // resolve.
728 if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
729 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fRTFBOID));
730 GrAssert(0 != rtIDs.fRTFBOID);
731 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
732 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
733 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
734 GR_GLEXT(fExts,
735 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
736 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
737 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
738 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000739 return return_null_texture();
740 }
741 } else {
742 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
743 }
744 int attempts = 1;
745 if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
746 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
747 GrAssert(0 != rtIDs.fStencilRenderbufferID);
748 attempts = GR_ARRAY_COUNT(GR_GL_STENCIL_FORMAT_ARRAY);
749 }
750
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000751 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000752 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000753 // (seems unlikely)
reed@google.comac10a2d2010-12-22 21:39:39 +0000754 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000755
756 err = ~GL_NO_ERROR;
757 for (int i = 0; i < attempts; ++i) {
758 if (rtIDs.fStencilRenderbufferID) {
759 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
760 rtIDs.fStencilRenderbufferID));
761 if (samples > 1) {
762 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
763 GR_RENDERBUFFER,
764 samples,
765 GR_GL_STENCIL_FORMAT_ARRAY[i],
766 glDesc.fAllocWidth,
767 glDesc.fAllocHeight));
768 } else {
769 GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
770 GR_RENDERBUFFER,
771 GR_GL_STENCIL_FORMAT_ARRAY[i],
772 glDesc.fAllocWidth,
773 glDesc.fAllocHeight));
774 }
775 err = glGetError();
776 if (err != GL_NO_ERROR) {
777 continue;
778 }
779 }
780 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
781 GrAssert(samples > 1);
782 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
783 rtIDs.fMSColorRenderbufferID));
784 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
785 GR_RENDERBUFFER,
786 samples,
787 msColorRenderbufferFormat,
788 glDesc.fAllocWidth,
789 glDesc.fAllocHeight));
790 err = glGetError();
791 if (err != GL_NO_ERROR) {
792 continue;
793 }
794 }
795 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
796
797#if GR_COLLECT_STATS
798 ++fStats.fRenderTargetChngCnt;
799#endif
800 if (kIMG_MSFBO == fMSFBOType && samples > 1) {
801 GR_GLEXT(fExts, FramebufferTexture2DMultisample(
802 GR_FRAMEBUFFER,
803 GR_COLOR_ATTACHMENT0,
804 GL_TEXTURE_2D,
805 glDesc.fTextureID,
806 0,
807 samples));
808
809 } else {
810 GR_GLEXT(fExts, FramebufferTexture2D(GR_FRAMEBUFFER,
811 GR_COLOR_ATTACHMENT0,
812 GL_TEXTURE_2D,
813 glDesc.fTextureID, 0));
814 }
815 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
816 GLenum status = GR_GLEXT(fExts,
817 CheckFramebufferStatus(GR_FRAMEBUFFER));
818 if (status != GR_FRAMEBUFFER_COMPLETE) {
819 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
820 status, desc.fWidth, desc.fHeight);
821 continue;
822 }
823 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
824 #if GR_COLLECT_STATS
825 ++fStats.fRenderTargetChngCnt;
826 #endif
827 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
828 GR_COLOR_ATTACHMENT0,
829 GR_RENDERBUFFER,
830 rtIDs.fMSColorRenderbufferID));
831
832 }
833 if (rtIDs.fStencilRenderbufferID) {
834 // bind the stencil to rt fbo if present, othewise the tex fbo
835 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
836 GR_STENCIL_ATTACHMENT,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000837 GR_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000838 rtIDs.fStencilRenderbufferID));
839 }
840 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
841
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000842#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000843 // On some implementations you have to be bound as DEPTH_STENCIL.
844 // (Even binding to DEPTH and STENCIL separately with the same
845 // buffer doesn't work.)
846 if (rtIDs.fStencilRenderbufferID &&
847 status != GR_FRAMEBUFFER_COMPLETE) {
848 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
849 GR_STENCIL_ATTACHMENT,
850 GR_RENDERBUFFER,
851 0));
852 GR_GLEXT(fExts,
853 FramebufferRenderbuffer(GR_FRAMEBUFFER,
854 GR_DEPTH_STENCIL_ATTACHMENT,
855 GR_RENDERBUFFER,
856 rtIDs.fStencilRenderbufferID));
857 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
858 }
859#endif
860 if (status != GR_FRAMEBUFFER_COMPLETE) {
861 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
862 status, desc.fWidth, desc.fHeight);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000863#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000864 if (rtIDs.fStencilRenderbufferID) {
865 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
866 GR_DEPTH_STENCIL_ATTACHMENT,
867 GR_RENDERBUFFER,
868 0));
869 }
870#endif
871 continue;
872 }
873 // we're successful!
874 failed = false;
875 break;
876 }
877 if (failed) {
878 if (rtIDs.fStencilRenderbufferID) {
879 GR_GLEXT(fExts,
880 DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
881 }
882 if (rtIDs.fMSColorRenderbufferID) {
883 GR_GLEXT(fExts,
884 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
885 }
886 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
887 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
888 }
889 if (rtIDs.fTexFBOID) {
890 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
891 }
892 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
893 return return_null_texture();
894 }
895 }
896#ifdef TRACE_TEXTURE_CREATION
897 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
898 tex->fTextureID, width, height, tex->fUploadByteCount);
899#endif
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000900 GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, DEFAULT_PARAMS, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000901
902 if (0 != rtIDs.fTexFBOID) {
903 GrRenderTarget* rt = tex->asRenderTarget();
904 // We've messed with FBO state but may not have set the correct viewport
905 // so just dirty the rendertarget state to force a resend.
906 fHWDrawState.fRenderTarget = NULL;
907
908 // clear the new stencil buffer if we have one
909 if (!(desc.fFlags & kNoPathRendering_TextureFlag)) {
910 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
911 fCurrDrawState.fRenderTarget = rt;
912 eraseStencil(0, ~0);
913 fCurrDrawState.fRenderTarget = rtSave;
914 }
915 }
916 return tex;
917}
918
reed@google.comac10a2d2010-12-22 21:39:39 +0000919GrVertexBuffer* GrGpuGL::createVertexBuffer(uint32_t size, bool dynamic) {
920 GLuint id;
921 GR_GL(GenBuffers(1, &id));
922 if (id) {
923 GR_GL(BindBuffer(GL_ARRAY_BUFFER, id));
924 GrGLClearErr();
925 // make sure driver can allocate memory for this buffer
926 GR_GL_NO_ERR(BufferData(GL_ARRAY_BUFFER, size, NULL,
927 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
928 if (glGetError() != GL_NO_ERROR) {
929 GR_GL(DeleteBuffers(1, &id));
930 // deleting bound buffer does implicit bind to 0
931 fHWGeometryState.fVertexBuffer = NULL;
932 return NULL;
933 }
934 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this,
935 size, dynamic);
936 fHWGeometryState.fVertexBuffer = vertexBuffer;
937 return vertexBuffer;
938 }
939 return NULL;
940}
941
942GrIndexBuffer* GrGpuGL::createIndexBuffer(uint32_t size, bool dynamic) {
943 GLuint id;
944 GR_GL(GenBuffers(1, &id));
945 if (id) {
946 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, id));
947 GrGLClearErr();
948 // make sure driver can allocate memory for this buffer
949 GR_GL_NO_ERR(BufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL,
950 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
951 if (glGetError() != GL_NO_ERROR) {
952 GR_GL(DeleteBuffers(1, &id));
953 // deleting bound buffer does implicit bind to 0
954 fHWGeometryState.fIndexBuffer = NULL;
955 return NULL;
956 }
957 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this,
958 size, dynamic);
959 fHWGeometryState.fIndexBuffer = indexBuffer;
960 return indexBuffer;
961 }
962 return NULL;
963}
964
reed@google.comac10a2d2010-12-22 21:39:39 +0000965void GrGpuGL::flushScissor(const GrIRect* rect) {
966 GrAssert(NULL != fCurrDrawState.fRenderTarget);
967 const GrIRect& vp =
968 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
969
970 if (NULL != rect &&
971 rect->contains(vp)) {
972 rect = NULL;
973 }
974
975 if (NULL != rect) {
976 GrIRect scissor;
977 // viewport is already in GL coords
978 // create a scissor in GL coords (top > bottom)
979 scissor.setLTRB(vp.fLeft + rect->fLeft,
980 vp.fTop - rect->fTop,
981 vp.fLeft + rect->fRight,
982 vp.fTop - rect->fBottom);
983
984 if (fHWBounds.fScissorRect != scissor) {
985 GR_GL(Scissor(scissor.fLeft, scissor.fBottom,
986 scissor.width(), -scissor.height()));
987 fHWBounds.fScissorRect = scissor;
988 }
989
990 if (!fHWBounds.fScissorEnabled) {
991 GR_GL(Enable(GL_SCISSOR_TEST));
992 fHWBounds.fScissorEnabled = true;
993 }
994 } else {
995 if (fHWBounds.fScissorEnabled) {
996 GR_GL(Disable(GL_SCISSOR_TEST));
997 fHWBounds.fScissorEnabled = false;
998 }
999 }
1000}
1001
reed@google.comac10a2d2010-12-22 21:39:39 +00001002void GrGpuGL::eraseColor(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001003 if (NULL == fCurrDrawState.fRenderTarget) {
1004 return;
1005 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001006 flushRenderTarget();
1007 if (fHWBounds.fScissorEnabled) {
1008 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001009 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001010 }
1011 GR_GL(ColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE));
1012 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1013 GrColorUnpackG(color)/255.f,
1014 GrColorUnpackB(color)/255.f,
1015 GrColorUnpackA(color)/255.f));
1016 GR_GL(Clear(GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001017 fWriteMaskChanged = true;
1018}
1019
1020void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001021 if (NULL == fCurrDrawState.fRenderTarget) {
1022 return;
1023 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001024 flushRenderTarget();
1025 if (fHWBounds.fScissorEnabled) {
1026 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001027 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001028 }
1029 GR_GL(StencilMask(mask));
1030 GR_GL(ClearStencil(value));
1031 GR_GL(Clear(GL_STENCIL_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001032 fWriteMaskChanged = true;
1033}
1034
1035void GrGpuGL::eraseStencilClip() {
1036 GLint stencilBitCount;
reed@google.comac20fb92011-01-12 17:14:53 +00001037 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001038 GrAssert(stencilBitCount > 0);
1039 GLint clipStencilMask = (1 << (stencilBitCount - 1));
1040 eraseStencil(0, clipStencilMask);
1041}
1042
1043void GrGpuGL::forceRenderTargetFlush() {
1044 flushRenderTarget();
1045}
1046
1047bool GrGpuGL::readPixels(int left, int top, int width, int height,
1048 GrTexture::PixelConfig config, void* buffer) {
1049 GLenum internalFormat; // we don't use this for glReadPixels
1050 GLenum format;
1051 GLenum type;
1052 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1053 return false;
1054 }
1055
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001056 if (NULL == fCurrDrawState.fRenderTarget) {
1057 return false;
1058 }
1059 flushRenderTarget();
1060
reed@google.comac10a2d2010-12-22 21:39:39 +00001061 const GrIRect& vp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1062
1063 // Brian says that viewport rects are already upside down (grrrrr)
bsalomon@google.com316f99232011-01-13 21:28:12 +00001064 GR_GL(ReadPixels(left, -vp.height() - top - height, width, height,
1065 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001066
1067 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1068 // API presents top-to-bottom
1069 {
1070 size_t stride = width * GrTexture::BytesPerPixel(config);
1071 GrAutoMalloc rowStorage(stride);
1072 void* tmp = rowStorage.get();
1073
1074 const int halfY = height >> 1;
1075 char* top = reinterpret_cast<char*>(buffer);
1076 char* bottom = top + (height - 1) * stride;
1077 for (int y = 0; y < halfY; y++) {
1078 memcpy(tmp, top, stride);
1079 memcpy(top, bottom, stride);
1080 memcpy(bottom, tmp, stride);
1081 top += stride;
1082 bottom -= stride;
1083 }
1084 }
1085 return true;
1086}
1087
1088void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001089
1090 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1091
reed@google.comac10a2d2010-12-22 21:39:39 +00001092 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1093 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
1094 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
1095 #if GR_COLLECT_STATS
1096 ++fStats.fRenderTargetChngCnt;
1097 #endif
1098 rt->setDirty(true);
1099 #if GR_DEBUG
1100 GLenum status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
1101 if (status != GR_FRAMEBUFFER_COMPLETE) {
1102 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1103 }
1104 #endif
1105 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
1106 const GrIRect& vp = rt->viewport();
1107 fRenderTargetChanged = true;
1108 if (fHWBounds.fViewportRect != vp) {
1109 GR_GL(Viewport(vp.fLeft,
1110 vp.fBottom,
1111 vp.width(),
1112 -vp.height()));
1113 fHWBounds.fViewportRect = vp;
1114 }
1115 }
1116}
1117
1118GLenum gPrimitiveType2GLMode[] = {
1119 GL_TRIANGLES,
1120 GL_TRIANGLE_STRIP,
1121 GL_TRIANGLE_FAN,
1122 GL_POINTS,
1123 GL_LINES,
1124 GL_LINE_STRIP
1125};
1126
1127void GrGpuGL::drawIndexedHelper(PrimitiveType type,
1128 uint32_t startVertex,
1129 uint32_t startIndex,
1130 uint32_t vertexCount,
1131 uint32_t indexCount) {
1132 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1133
1134 GLvoid* indices = (GLvoid*)(sizeof(uint16_t) * startIndex);
1135 if (kReserved_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1136 indices = (GLvoid*)((intptr_t)indices + (intptr_t)fIndices.get());
1137 } else if (kArray_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1138 indices = (GLvoid*)((intptr_t)indices +
1139 (intptr_t)fGeometrySrc.fIndexArray);
1140 }
1141
1142 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1143 GL_UNSIGNED_SHORT, indices));
1144}
1145
1146void GrGpuGL::drawNonIndexedHelper(PrimitiveType type,
1147 uint32_t startVertex,
1148 uint32_t vertexCount) {
1149 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1150
1151 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1152}
1153
reed@google.comac10a2d2010-12-22 21:39:39 +00001154void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1155 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1156
1157 if (NULL != rt && rt->needsResolve()) {
1158 GrAssert(kNone_MSFBO != fMSFBOType);
1159 GrAssert(rt->textureFBOID() != rt->renderFBOID());
1160 GR_GLEXT(fExts, BindFramebuffer(GR_READ_FRAMEBUFFER,
1161 rt->renderFBOID()));
1162 GR_GLEXT(fExts, BindFramebuffer(GR_DRAW_FRAMEBUFFER,
1163 rt->textureFBOID()));
1164 #if GR_COLLECT_STATS
1165 ++fStats.fRenderTargetChngCnt;
1166 #endif
1167 // make sure we go through set render target
1168 fHWDrawState.fRenderTarget = NULL;
1169
1170 GLint left = 0;
1171 GLint right = texture->contentWidth();
1172 // we will have rendered to the top of the FBO.
1173 GLint top = texture->allocHeight();
1174 GLint bottom = texture->allocHeight() - texture->contentHeight();
1175 if (kApple_MSFBO == fMSFBOType) {
1176 GR_GL(Enable(GL_SCISSOR_TEST));
1177 GR_GL(Scissor(left, bottom, right-left, top-bottom));
1178 GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
1179 fHWBounds.fScissorRect.setEmpty();
1180 fHWBounds.fScissorEnabled = true;
1181 } else {
1182 GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
1183 left, bottom, right, top,
1184 GL_COLOR_BUFFER_BIT, GL_NEAREST));
1185 }
1186 rt->setDirty(false);
1187
1188 }
1189}
1190
1191void GrGpuGL::flushStencil() {
1192
1193 // use stencil for clipping if clipping is enabled and the clip
1194 // has been written into the stencil.
1195 bool stencilClip = fClipState.fClipInStencil &&
1196 (kClip_StateBit & fCurrDrawState.fFlagBits);
1197 bool stencilChange =
1198 fWriteMaskChanged ||
1199 fHWStencilClip != stencilClip ||
1200 fHWDrawState.fStencilPass != fCurrDrawState.fStencilPass ||
1201 (kNone_StencilPass != fCurrDrawState.fStencilPass &&
1202 (StencilPass)kSetClip_StencilPass != fCurrDrawState.fStencilPass &&
1203 fHWDrawState.fReverseFill != fCurrDrawState.fReverseFill);
1204
1205 if (stencilChange) {
1206 GLint stencilBitCount;
1207 GLint clipStencilMask;
1208 GLint pathStencilMask;
reed@google.comac20fb92011-01-12 17:14:53 +00001209 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001210 GrAssert(stencilBitCount > 0 ||
1211 kNone_StencilPass == fCurrDrawState.fStencilPass);
1212 clipStencilMask = (1 << (stencilBitCount - 1));
1213 pathStencilMask = clipStencilMask - 1;
1214 switch (fCurrDrawState.fStencilPass) {
1215 case kNone_StencilPass:
1216 if (stencilClip) {
1217 GR_GL(Enable(GL_STENCIL_TEST));
1218 GR_GL(StencilFunc(GL_EQUAL,
1219 clipStencilMask,
1220 clipStencilMask));
1221 GR_GL(StencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
1222 } else {
1223 GR_GL(Disable(GL_STENCIL_TEST));
1224 }
1225 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1226 if (!fSingleStencilPassForWinding) {
1227 GR_GL(Disable(GL_CULL_FACE));
1228 }
1229 break;
1230 case kEvenOddStencil_StencilPass:
1231 GR_GL(Enable(GL_STENCIL_TEST));
1232 if (stencilClip) {
1233 GR_GL(StencilFunc(GL_EQUAL, clipStencilMask, clipStencilMask));
1234 } else {
1235 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1236 }
1237 GR_GL(StencilMask(pathStencilMask));
1238 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1239 GR_GL(StencilOp(GL_KEEP, GL_INVERT, GL_INVERT));
1240 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1241 if (!fSingleStencilPassForWinding) {
1242 GR_GL(Disable(GL_CULL_FACE));
1243 }
1244 break;
1245 case kEvenOddColor_StencilPass: {
1246 GR_GL(Enable(GL_STENCIL_TEST));
1247 GLint funcRef = 0;
1248 GLuint funcMask = pathStencilMask;
1249 if (stencilClip) {
1250 funcRef |= clipStencilMask;
1251 funcMask |= clipStencilMask;
1252 }
1253 if (!fCurrDrawState.fReverseFill) {
1254 funcRef |= pathStencilMask;
1255 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001256 GR_GL(StencilFunc(GL_EQUAL, funcRef, funcMask));
1257 GR_GL(StencilMask(pathStencilMask));
reed@google.comac10a2d2010-12-22 21:39:39 +00001258 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1259 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1260 if (!fSingleStencilPassForWinding) {
1261 GR_GL(Disable(GL_CULL_FACE));
1262 }
1263 } break;
1264 case kWindingStencil1_StencilPass:
1265 GR_GL(Enable(GL_STENCIL_TEST));
1266 if (fHasStencilWrap) {
1267 if (stencilClip) {
1268 GR_GL(StencilFunc(GL_EQUAL,
1269 clipStencilMask,
1270 clipStencilMask));
1271 } else {
1272 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1273 }
1274 if (fSingleStencilPassForWinding) {
1275 GR_GL(StencilOpSeparate(GL_FRONT, GL_KEEP,
1276 GL_INCR_WRAP, GL_INCR_WRAP));
1277 GR_GL(StencilOpSeparate(GL_BACK, GL_KEEP,
1278 GL_DECR_WRAP, GL_DECR_WRAP));
1279 } else {
1280 GR_GL(StencilOp(GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP));
1281 GR_GL(Enable(GL_CULL_FACE));
1282 GR_GL(CullFace(GL_BACK));
1283 }
1284 } else {
1285 // If we don't have wrap then we use the Func to detect
1286 // values that would wrap (0 on decr and mask on incr). We
1287 // make the func fail on these values and use the sfail op
1288 // to effectively wrap by inverting.
1289 // This applies whether we are doing a two-pass (front faces
1290 // followed by back faces) or a single pass (separate func/op)
1291
1292 // Note that in the case where we are also using stencil to
1293 // clip this means we will write into the path bits in clipped
1294 // out pixels. We still apply the clip bit in the color pass
1295 // stencil func so we don't draw color outside the clip.
1296 // We also will clear the stencil bits in clipped pixels by
1297 // using zero in the sfail op with write mask set to the
1298 // path mask.
1299 GR_GL(Enable(GL_STENCIL_TEST));
1300 if (fSingleStencilPassForWinding) {
1301 GR_GL(StencilFuncSeparate(GL_FRONT,
1302 GL_NOTEQUAL,
1303 pathStencilMask,
1304 pathStencilMask));
1305 GR_GL(StencilFuncSeparate(GL_BACK,
1306 GL_NOTEQUAL,
1307 0x0,
1308 pathStencilMask));
1309 GR_GL(StencilOpSeparate(GL_FRONT, GL_INVERT,
1310 GL_INCR, GL_INCR));
1311 GR_GL(StencilOpSeparate(GL_BACK, GL_INVERT,
1312 GL_DECR, GL_DECR));
1313 } else {
1314 GR_GL(StencilFunc(GL_NOTEQUAL,
1315 pathStencilMask,
1316 pathStencilMask));
1317 GR_GL(StencilOp(GL_INVERT, GL_INCR, GL_INCR));
1318 GR_GL(Enable(GL_CULL_FACE));
1319 GR_GL(CullFace(GL_BACK));
1320 }
1321 }
1322 GR_GL(StencilMask(pathStencilMask));
1323 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1324 break;
1325 case kWindingStencil2_StencilPass:
1326 GrAssert(!fSingleStencilPassForWinding);
1327 GR_GL(Enable(GL_STENCIL_TEST));
1328 if (fHasStencilWrap) {
1329 if (stencilClip) {
1330 GR_GL(StencilFunc(GL_EQUAL,
1331 clipStencilMask,
1332 clipStencilMask));
1333 } else {
1334 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1335 }
1336 GR_GL(StencilOp(GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP));
1337 } else {
1338 GR_GL(StencilFunc(GL_NOTEQUAL, 0x0, pathStencilMask));
1339 GR_GL(StencilOp(GL_INVERT, GL_DECR, GL_DECR));
1340 }
1341 GR_GL(StencilMask(pathStencilMask));
1342 GR_GL(Enable(GL_CULL_FACE));
1343 GR_GL(CullFace(GL_FRONT));
1344 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1345 break;
1346 case kWindingColor_StencilPass: {
1347 GR_GL(Enable(GL_STENCIL_TEST));
1348 GLint funcRef = 0;
1349 GLuint funcMask = pathStencilMask;
1350 GLenum funcFunc;
1351 if (stencilClip) {
1352 funcRef |= clipStencilMask;
1353 funcMask |= clipStencilMask;
1354 }
1355 if (fCurrDrawState.fReverseFill) {
1356 funcFunc = GL_EQUAL;
1357 } else {
1358 funcFunc = GL_LESS;
1359 }
1360 GR_GL(StencilFunc(funcFunc, funcRef, funcMask));
1361 GR_GL(StencilMask(pathStencilMask));
1362 // must zero in sfail because winding w/o wrap will write
1363 // path stencil bits in clipped out pixels
1364 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1365 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1366 if (!fSingleStencilPassForWinding) {
1367 GR_GL(Disable(GL_CULL_FACE));
1368 }
1369 } break;
1370 case kSetClip_StencilPass:
1371 GR_GL(Enable(GL_STENCIL_TEST));
1372 GR_GL(StencilFunc(GL_ALWAYS, clipStencilMask, clipStencilMask));
1373 GR_GL(StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
1374 GR_GL(StencilMask(clipStencilMask));
1375 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1376 if (!fSingleStencilPassForWinding) {
1377 GR_GL(Disable(GL_CULL_FACE));
1378 }
1379 break;
1380 default:
1381 GrAssert(!"Unexpected stencil pass.");
1382 break;
1383
1384 }
1385 fHWDrawState.fStencilPass = fCurrDrawState.fStencilPass;
1386 fHWDrawState.fReverseFill = fCurrDrawState.fReverseFill;
1387 fWriteMaskChanged = false;
1388 fHWStencilClip = stencilClip;
1389 }
1390}
1391
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001392bool GrGpuGL::flushGLStateCommon(PrimitiveType type) {
1393
1394 // GrGpu::setupClipAndFlushState should have already checked this
1395 // and bailed if not true.
1396 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001397
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001398 for (int s = 0; s < kNumStages; ++s) {
1399 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001400
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001401 // bind texture and set sampler state
1402 if (usingTexture) {
1403 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001404
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001405 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001406 // if we created a rt/tex and rendered to it without using a
1407 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001408 // the last bound texture, but it needs resolving. So keep this
1409 // out of the "last != next" check.
1410 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001411
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001412 if (fHWDrawState.fTextures[s] != nextTexture) {
1413 setTextureUnit(s);
1414 GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
1415 #if GR_COLLECT_STATS
1416 ++fStats.fTextureChngCnt;
1417 #endif
1418 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1419 fHWDrawState.fTextures[s] = nextTexture;
1420 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001421
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001422 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001423 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001424 nextTexture->getTexParams();
1425 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001426
1427 newTexParams.fFilter = sampler.isFilter() ? GL_LINEAR :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001428 GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001429 newTexParams.fWrapS =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001430 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001431 newTexParams.fWrapT =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001432 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001433
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001434 if (newTexParams.fFilter != oldTexParams.fFilter) {
1435 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001436 GR_GL(TexParameteri(GL_TEXTURE_2D,
1437 GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001438 newTexParams.fFilter));
bsalomon@google.com316f99232011-01-13 21:28:12 +00001439 GR_GL(TexParameteri(GL_TEXTURE_2D,
1440 GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001441 newTexParams.fFilter));
1442 }
1443 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1444 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001445 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001446 GL_TEXTURE_WRAP_S,
1447 newTexParams.fWrapS));
1448 }
1449 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1450 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001451 GR_GL(TexParameteri(GL_TEXTURE_2D,
1452 GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001453 newTexParams.fWrapT));
1454 }
1455 nextTexture->setTexParams(newTexParams);
1456 } else {
1457 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001458 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001459 }
1460 }
1461 }
1462
1463 flushRenderTarget();
1464
1465 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1466 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1467 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
1468 GR_GL(Enable(GL_DITHER));
1469 } else {
1470 GR_GL(Disable(GL_DITHER));
1471 }
1472 }
1473
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001474#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +00001475 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1476 // smooth lines.
1477 if (fRenderTargetChanged ||
1478 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1479 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1480 GLint msaa = 0;
1481 // only perform query if we know MSAA is supported.
1482 // calling on non-MSAA target caused a crash in one environment,
1483 // though I don't think it should.
1484 if (!fAASamples[kHigh_AALevel]) {
reed@google.comac20fb92011-01-12 17:14:53 +00001485 GR_GL_GetIntegerv(GL_SAMPLE_BUFFERS, &msaa);
reed@google.comac10a2d2010-12-22 21:39:39 +00001486 }
1487 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1488 if (msaa) {
1489 GR_GL(Enable(GL_MULTISAMPLE));
1490 } else {
1491 GR_GL(Enable(GL_LINE_SMOOTH));
1492 }
1493 } else {
1494 if (msaa) {
1495 GR_GL(Disable(GL_MULTISAMPLE));
1496 }
1497 GR_GL(Disable(GL_LINE_SMOOTH));
1498 }
1499 }
1500#endif
1501
1502 bool blendOff = canDisableBlend();
1503 if (fHWBlendDisabled != blendOff) {
1504 if (blendOff) {
1505 GR_GL(Disable(GL_BLEND));
1506 } else {
1507 GR_GL(Enable(GL_BLEND));
1508 }
1509 fHWBlendDisabled = blendOff;
1510 }
1511
1512 if (!blendOff) {
1513 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1514 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1515 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1516 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1517 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1518 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1519 }
1520 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001521
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001522#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001523 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001524 for (int s = 0; s < kNumStages; ++s) {
1525 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1526 NULL == fCurrDrawState.fRenderTarget ||
1527 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001528 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001529 fCurrDrawState.fRenderTarget);
1530 }
1531#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001532
reed@google.comac10a2d2010-12-22 21:39:39 +00001533 flushStencil();
1534
1535 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001536 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001537}
1538
1539void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
1540 fHWGeometryState.fVertexBuffer = buffer;
1541}
1542
1543void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1544 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1545 buffer == fGeometrySrc.fVertexBuffer));
1546
1547 if (fHWGeometryState.fVertexBuffer == buffer) {
1548 // deleting bound buffer does implied bind to 0
1549 fHWGeometryState.fVertexBuffer = NULL;
1550 }
1551}
1552
1553void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1554 fGeometrySrc.fIndexBuffer = buffer;
1555}
1556
1557void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1558 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1559 buffer == fGeometrySrc.fIndexBuffer));
1560
1561 if (fHWGeometryState.fIndexBuffer == buffer) {
1562 // deleting bound buffer does implied bind to 0
1563 fHWGeometryState.fIndexBuffer = NULL;
1564 }
1565}
1566
reed@google.comac10a2d2010-12-22 21:39:39 +00001567void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1568 GrAssert(NULL != renderTarget);
1569
1570 // if the bound FBO is destroyed we can't rely on the implicit bind to 0
1571 // a) we want the default RT which may not be FBO 0
1572 // b) we set more state than just FBO based on the RT
1573 // So trash the HW state to force an RT flush next time
1574 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001575 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001576 }
1577 if (fHWDrawState.fRenderTarget == renderTarget) {
1578 fHWDrawState.fRenderTarget = NULL;
1579 }
1580 if (fClipState.fStencilClipTarget == renderTarget) {
1581 fClipState.fStencilClipTarget = NULL;
1582 }
1583}
1584
1585void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001586 for (int s = 0; s < kNumStages; ++s) {
1587 if (fCurrDrawState.fTextures[s] == texture) {
1588 fCurrDrawState.fTextures[s] = NULL;
1589 }
1590 if (fHWDrawState.fTextures[s] == texture) {
1591 // deleting bound texture does implied bind to 0
1592 fHWDrawState.fTextures[s] = NULL;
1593 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001594 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001595}
1596
1597void GrGpuGL::notifyTextureRemoveRenderTarget(GrGLTexture* texture) {
1598 GrAssert(NULL != texture->asRenderTarget());
1599
1600 // if there is a pending resolve, perform it.
1601 resolveTextureRenderTarget(texture);
1602}
1603
1604bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
1605 GLenum* internalFormat,
1606 GLenum* format,
1607 GLenum* type) {
1608 switch (config) {
1609 case GrTexture::kRGBA_8888_PixelConfig:
1610 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001611 *format = GR_GL_32BPP_COLOR_FORMAT;
reed@google.com63100f92011-01-18 21:32:14 +00001612#if GR_SUPPORT_GLES
1613 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1614 // format for a BGRA is BGRA not RGBA (as on desktop)
1615 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1616#else
1617 *internalFormat = GL_RGBA;
bsalomon@google.comed3a0682011-01-18 16:54:04 +00001618#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001619 *type = GL_UNSIGNED_BYTE;
1620 break;
1621 case GrTexture::kRGB_565_PixelConfig:
1622 *format = GL_RGB;
1623 *internalFormat = GL_RGB;
1624 *type = GL_UNSIGNED_SHORT_5_6_5;
1625 break;
1626 case GrTexture::kRGBA_4444_PixelConfig:
1627 *format = GL_RGBA;
1628 *internalFormat = GL_RGBA;
1629 *type = GL_UNSIGNED_SHORT_4_4_4_4;
1630 break;
1631 case GrTexture::kIndex_8_PixelConfig:
1632 if (this->supports8BitPalette()) {
1633 *format = GR_PALETTE8_RGBA8;
1634 *internalFormat = GR_PALETTE8_RGBA8;
1635 *type = GL_UNSIGNED_BYTE; // unused I think
1636 } else {
1637 return false;
1638 }
1639 break;
1640 case GrTexture::kAlpha_8_PixelConfig:
1641 *format = GL_ALPHA;
1642 *internalFormat = GL_ALPHA;
1643 *type = GL_UNSIGNED_BYTE;
1644 break;
1645 default:
1646 return false;
1647 }
1648 return true;
1649}
1650
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001651void GrGpuGL::setTextureUnit(int unit) {
1652 GrAssert(unit >= 0 && unit < kNumStages);
1653 if (fActiveTextureUnitIdx != unit) {
1654 GR_GL(ActiveTexture(GL_TEXTURE0 + unit));
1655 fActiveTextureUnitIdx = unit;
1656 }
1657}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001658
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001659void GrGpuGL::setSpareTextureUnit() {
1660 if (fActiveTextureUnitIdx != (GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1661 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
1662 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1663 }
1664}
1665
reed@google.comac10a2d2010-12-22 21:39:39 +00001666/* On ES the internalFormat and format must match for TexImage and we use
1667 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1668 decide the internalFormat. However, on ES internalFormat for
1669 RenderBufferStorage* has to be a specific format (not a base format like
1670 GL_RGBA).
1671 */
1672bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) {
1673 switch (config) {
1674 case GrTexture::kRGBA_8888_PixelConfig:
1675 case GrTexture::kRGBX_8888_PixelConfig:
1676 if (fRGBA8Renderbuffer) {
1677 *format = GR_RGBA8;
1678 return true;
1679 } else {
1680 return false;
1681 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001682#if GR_SUPPORT_GLES // ES2 supports 565. ES1 supports it with FBO extension
1683 // desktop GL has no such internal format
reed@google.comac10a2d2010-12-22 21:39:39 +00001684 case GrTexture::kRGB_565_PixelConfig:
1685 *format = GR_RGB565;
1686 return true;
1687#endif
1688 case GrTexture::kRGBA_4444_PixelConfig:
1689 *format = GL_RGBA4;
1690 return true;
1691 default:
1692 return false;
1693 }
1694}