blob: ba133721ba4cb7a0afad8a0696776fcce97d96f7 [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.comc6cf7232011-02-17 16:43:10 +000052void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
53 GrSamplerState::SampleMode mode,
54 GrMatrix* matrix) {
55 GrAssert(NULL != texture);
56 GrAssert(NULL != matrix);
57 if (GR_Scalar1 != texture->contentScaleX() ||
58 GR_Scalar1 != texture->contentScaleY()) {
59 if (GrSamplerState::kRadial_SampleMode == mode) {
60 GrMatrix scale;
61 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
62 matrix->postConcat(scale);
63 } else if (GrSamplerState::kNormal_SampleMode == mode) {
64 GrMatrix scale;
65 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
66 matrix->postConcat(scale);
67 } else {
68 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
69 }
70 }
71 GrGLTexture::Orientation orientation = texture->orientation();
72 if (GrGLTexture::kBottomUp_Orientation == orientation) {
73 GrMatrix invY;
74 invY.setAll(GR_Scalar1, 0, 0,
75 0, -GR_Scalar1, GR_Scalar1,
76 0, 0, GrMatrix::I()[8]);
77 matrix->postConcat(invY);
78 } else {
79 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
80 }
81}
82
83bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
84 const GrSamplerState& sampler) {
85 GrAssert(NULL != texture);
86 if (!sampler.getMatrix().isIdentity()) {
87 return false;
88 }
89 if (GR_Scalar1 != texture->contentScaleX() ||
90 GR_Scalar1 != texture->contentScaleY()) {
91 return false;
92 }
93 GrGLTexture::Orientation orientation = texture->orientation();
94 if (GrGLTexture::kBottomUp_Orientation == orientation) {
95 return false;
96 } else {
97 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
98 }
99 return true;
100}
101
102///////////////////////////////////////////////////////////////////////////////
103
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000104static bool gPrintStartupSpew;
105
106
reed@google.comac10a2d2010-12-22 21:39:39 +0000107bool fbo_test(GrGLExts exts, int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000108
109 GLint savedFBO;
110 GLint savedTexUnit;
reed@google.com3d8de042011-01-20 02:18:00 +0000111 GR_GL_GetIntegerv(GL_ACTIVE_TEXTURE, &savedTexUnit);
112 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000113
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000114 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000115
reed@google.comac10a2d2010-12-22 21:39:39 +0000116 GLuint testFBO;
117 GR_GLEXT(exts, GenFramebuffers(1, &testFBO));
118 GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, testFBO));
119 GLuint testRTTex;
120 GR_GL(GenTextures(1, &testRTTex));
121 GR_GL(BindTexture(GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000122 // some implementations require texture to be mip-map complete before
123 // FBO with level 0 bound as color attachment will be framebuffer complete.
124 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +0000125 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h,
126 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
127 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
128 GR_GLEXT(exts, FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0,
129 GL_TEXTURE_2D, testRTTex, 0));
130 GLenum status = GR_GLEXT(exts, CheckFramebufferStatus(GR_FRAMEBUFFER));
131 GR_GLEXT(exts, DeleteFramebuffers(1, &testFBO));
132 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000133
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000134 GR_GL(ActiveTexture(savedTexUnit));
135 GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000136
reed@google.comac10a2d2010-12-22 21:39:39 +0000137 return status == GR_FRAMEBUFFER_COMPLETE;
138}
139
reed@google.comac10a2d2010-12-22 21:39:39 +0000140GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000141
reed@google.comeeeb5a02010-12-23 15:12:59 +0000142 if (gPrintStartupSpew) {
143 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
144 this);
145 GrPrintf("------ VENDOR %s\n", glGetString(GL_VENDOR));
146 GrPrintf("------ RENDERER %s\n", glGetString(GL_RENDERER));
147 GrPrintf("------ VERSION %s\n", glGetString(GL_VERSION));
148 GrPrintf("------ EXTENSIONS\n %s \n", glGetString(GL_EXTENSIONS));
149 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000150
151 GrGLClearErr();
152
153 GrGLInitExtensions(&fExts);
154
155 resetContextHelper();
156
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000157 resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000158
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000159 GLint maxTextureUnits;
160 // check FS and fixed-function texture unit limits
161 // we only use textures in the fragment stage currently.
162 // checks are > to make sure we have a spare unit.
163#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES2
reed@google.com3d8de042011-01-20 02:18:00 +0000164 GR_GL_GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000165 GrAssert(maxTextureUnits > kNumStages);
166#endif
167#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1
reed@google.com3d8de042011-01-20 02:18:00 +0000168 GR_GL_GetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000169 GrAssert(maxTextureUnits > kNumStages);
170#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +0000171
reed@google.comac10a2d2010-12-22 21:39:39 +0000172 fCurrDrawState = fHWDrawState;
173
174 ////////////////////////////////////////////////////////////////////////////
175 // Check for supported features.
176
177 int major, minor;
178 gl_version(&major, &minor);
179
180 GLint numFormats;
reed@google.comac20fb92011-01-12 17:14:53 +0000181 GR_GL_GetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000182 GrAutoSTMalloc<10, GLint> formats(numFormats);
reed@google.comac20fb92011-01-12 17:14:53 +0000183 GR_GL_GetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000184 for (int i = 0; i < numFormats; ++i) {
185 if (formats[i] == GR_PALETTE8_RGBA8) {
186 f8bitPaletteSupport = true;
187 break;
188 }
189 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000190
191 if (gPrintStartupSpew) {
192 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
193 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000194
195 GR_STATIC_ASSERT(0 == kNone_AALevel);
196 GR_STATIC_ASSERT(1 == kLow_AALevel);
197 GR_STATIC_ASSERT(2 == kMed_AALevel);
198 GR_STATIC_ASSERT(3 == kHigh_AALevel);
199
200 memset(fAASamples, 0, sizeof(fAASamples));
201 fMSFBOType = kNone_MSFBO;
202 if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
203 fMSFBOType = kIMG_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000204 if (gPrintStartupSpew) {
205 GrPrintf("MSAA Support: IMG ES EXT.\n");
206 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000207 }
208 else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
209 fMSFBOType = kApple_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000210 if (gPrintStartupSpew) {
211 GrPrintf("MSAA Support: APPLE ES EXT.\n");
212 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000213 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000214#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 else if ((major >= 3) ||
216 has_gl_extension("GL_ARB_framebuffer_object") ||
217 (has_gl_extension("GL_EXT_framebuffer_multisample") &&
218 has_gl_extension("GL_EXT_framebuffer_blit"))) {
219 fMSFBOType = kDesktop_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000220 if (gPrintStartupSpew) {
221 GrPrintf("MSAA Support: DESKTOP\n");
222 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000223 }
224#endif
225 else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000226 if (gPrintStartupSpew) {
227 GrPrintf("MSAA Support: NONE\n");
228 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000229 }
230
231 if (kNone_MSFBO != fMSFBOType) {
232 GLint maxSamples;
233 GLenum maxSampleGetter = (kIMG_MSFBO == fMSFBOType) ?
234 GR_MAX_SAMPLES_IMG :
235 GR_MAX_SAMPLES;
reed@google.comac20fb92011-01-12 17:14:53 +0000236 GR_GL_GetIntegerv(maxSampleGetter, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000237 if (maxSamples > 1 ) {
238 fAASamples[kNone_AALevel] = 0;
239 fAASamples[kLow_AALevel] = GrMax(2,
240 GrFixedFloorToInt((GR_FixedHalf) *
241 maxSamples));
242 fAASamples[kMed_AALevel] = GrMax(2,
243 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
244 maxSamples));
245 fAASamples[kHigh_AALevel] = maxSamples;
246 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000247 if (gPrintStartupSpew) {
248 GrPrintf("\tMax Samples: %d\n", maxSamples);
249 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000250 }
251
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000252#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000253 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
254 has_gl_extension("GL_EXT_stencil_wrap");
255#else
256 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
257#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000258 if (gPrintStartupSpew) {
259 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
260 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000261
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000262#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000263 // we could also look for GL_ATI_separate_stencil extension or
264 // GL_EXT_stencil_two_side but they use different function signatures
265 // than GL2.0+ (and than each other).
266 fSingleStencilPassForWinding = (major >= 2);
267#else
268 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
269 // an ES1 extension.
270 fSingleStencilPassForWinding = (major >= 2);
271#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000272 if (gPrintStartupSpew) {
273 GrPrintf("Single Stencil Pass For Winding: %s\n", (fSingleStencilPassForWinding ? "YES" : "NO"));
274 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000275
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000276#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000277 fRGBA8Renderbuffer = true;
278#else
279 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
280#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000281 if (gPrintStartupSpew) {
282 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
283 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000284
bsalomon@google.comed3a0682011-01-18 16:54:04 +0000285#if GR_SUPPORT_GLES
286 if (GR_GL_32BPP_COLOR_FORMAT == GR_BGRA) {
287 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
288 }
289#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000290
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000291#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000292 fBufferLockSupport = true; // we require VBO support and the desktop VBO
293 // extension includes glMapBuffer.
294#else
295 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
296#endif
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000297
reed@google.comeeeb5a02010-12-23 15:12:59 +0000298 if (gPrintStartupSpew) {
299 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
300 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000301
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000302#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com0748f212011-02-01 22:56:16 +0000303 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
304 fNPOTTextureTileSupport = true;
305 fNPOTTextureSupport = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000306 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000307 fNPOTTextureTileSupport = false;
308 fNPOTTextureSupport = false;
309 }
310#else
311 if (major >= 2) {
312 fNPOTTextureSupport = true;
313 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
314 } else {
315 fNPOTTextureSupport = has_gl_extension("GL_APPLE_texture_2D_limited_npot");
316 fNPOTTextureTileSupport = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000317 }
318#endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000319
reed@google.comac10a2d2010-12-22 21:39:39 +0000320 ////////////////////////////////////////////////////////////////////////////
321 // Experiments to determine limitations that can't be queried. TODO: Make
322 // these a preprocess that generate some compile time constants.
323
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000324 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000325
bsalomon@google.com0748f212011-02-01 22:56:16 +0000326 bool simpleFBOSuccess = fbo_test(fExts, 128, 128);
327 if (gPrintStartupSpew) {
328 if (!simpleFBOSuccess) {
329 GrPrintf("FBO Sanity Test: FAILED\n");
330 } else {
331 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000332 }
333 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000334 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000335
reed@google.comac10a2d2010-12-22 21:39:39 +0000336 /* Experimentation has found that some GLs that support NPOT textures
337 do not support FBOs with a NPOT texture. They report "unsupported" FBO
338 status. I don't know how to explicitly query for this. Do an
339 experiment. Note they may support NPOT with a renderbuffer but not a
340 texture. Presumably, the implementation bloats the renderbuffer
341 internally to the next POT.
342 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000343 bool fNPOTRenderTargetSupport = false;
344 if (fNPOTTextureSupport) {
345 fNPOTRenderTargetSupport = fbo_test(fExts, 200, 200);
346 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000347
bsalomon@google.com0748f212011-02-01 22:56:16 +0000348 if (gPrintStartupSpew) {
349 if (fNPOTTextureSupport) {
350 GrPrintf("NPOT textures supported\n");
351 if (fNPOTTextureTileSupport) {
352 GrPrintf("NPOT texture tiling supported\n");
353 } else {
354 GrPrintf("NPOT texture tiling NOT supported\n");
355 }
356 if (fNPOTRenderTargetSupport) {
357 GrPrintf("NPOT render targets supported\n");
358 } else {
359 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000360 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000361 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000362 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000363 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000364 }
365
reed@google.comac10a2d2010-12-22 21:39:39 +0000366 /* The iPhone 4 has a restriction that for an FBO with texture color
367 attachment with height <= 8 then the width must be <= height. Here
368 we look for such a limitation.
369 */
370 fMinRenderTargetHeight = GR_INVAL_GLINT;
371 GLint maxRenderSize;
reed@google.comac20fb92011-01-12 17:14:53 +0000372 GR_GL_GetIntegerv(GR_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000373
reed@google.comeeeb5a02010-12-23 15:12:59 +0000374 if (gPrintStartupSpew) {
375 GrPrintf("Small height FBO texture experiments\n");
376 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000377
378 for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000379 GLuint w = maxRenderSize;
380 GLuint h = i;
381 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000382 if (gPrintStartupSpew) {
383 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
384 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000385 fMinRenderTargetHeight = i;
386 break;
387 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000388 if (gPrintStartupSpew) {
389 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
390 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000391 }
392 }
393 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
394
reed@google.comeeeb5a02010-12-23 15:12:59 +0000395 if (gPrintStartupSpew) {
396 GrPrintf("Small width FBO texture experiments\n");
397 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000398 fMinRenderTargetWidth = GR_MAX_GLUINT;
bsalomon@google.com0748f212011-02-01 22:56:16 +0000399 for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000400 GLuint w = i;
401 GLuint h = maxRenderSize;
402 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000403 if (gPrintStartupSpew) {
404 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
405 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000406 fMinRenderTargetWidth = i;
407 break;
408 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000409 if (gPrintStartupSpew) {
410 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
411 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000412 }
413 }
414 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
415
reed@google.com02a7e6c2011-01-28 21:21:49 +0000416 GR_GL_GetIntegerv(GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000417}
418
419GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000420}
421
422void GrGpuGL::resetContextHelper() {
423// We detect cases when blending is effectively off
424 fHWBlendDisabled = false;
425 GR_GL(Enable(GL_BLEND));
426
427 // this is always disabled
428 GR_GL(Disable(GL_CULL_FACE));
429
430 GR_GL(Disable(GL_DITHER));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000431#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000432 GR_GL(Disable(GL_LINE_SMOOTH));
433 GR_GL(Disable(GL_POINT_SMOOTH));
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000434 GR_GL(Disable(GL_MULTISAMPLE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000435#endif
436
437 // we only ever use lines in hairline mode
438 GR_GL(LineWidth(1));
439
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000440 // invalid
441 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000442
443 fHWDrawState.fFlagBits = 0;
444
445 // illegal values
446 fHWDrawState.fSrcBlend = (BlendCoeff)-1;
447 fHWDrawState.fDstBlend = (BlendCoeff)-1;
448 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000449
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000450 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000451
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000452 for (int s = 0; s < kNumStages; ++s) {
453 fHWDrawState.fTextures[s] = NULL;
454 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
455 -GR_ScalarMax,
456 true);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000457
458 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000459 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000460
reed@google.comac10a2d2010-12-22 21:39:39 +0000461 GR_GL(Scissor(0,0,0,0));
462 fHWBounds.fScissorRect.setLTRB(0,0,0,0);
463 fHWBounds.fScissorEnabled = false;
464 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000465 fHWBounds.fViewportRect.setLTRB(-1,-1,-1,-1);
reed@google.comac10a2d2010-12-22 21:39:39 +0000466
reed@google.comac10a2d2010-12-22 21:39:39 +0000467 // disabling the stencil test also disables
468 // stencil buffer writes
469 GR_GL(Disable(GL_STENCIL_TEST));
470 GR_GL(StencilMask(0xffffffff));
471 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
472 fHWDrawState.fReverseFill = false;
473 fHWDrawState.fStencilPass = kNone_StencilPass;
474 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000475 fClipState.fClipIsDirty = true;
476 fClipState.fStencilClipTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000477
478 fHWGeometryState.fIndexBuffer = NULL;
479 fHWGeometryState.fVertexBuffer = NULL;
480 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
481 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000482 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000483
484 fHWDrawState.fRenderTarget = NULL;
485}
486
487void GrGpuGL::resetContext() {
488 INHERITED::resetContext();
489 resetContextHelper();
490}
491
reed@google.comac10a2d2010-12-22 21:39:39 +0000492GrRenderTarget* GrGpuGL::createPlatformRenderTarget(
493 intptr_t platformRenderTarget,
494 int width, int height) {
495 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
496 rtIDs.fStencilRenderbufferID = 0;
497 rtIDs.fMSColorRenderbufferID = 0;
498 rtIDs.fTexFBOID = 0;
499 rtIDs.fOwnIDs = false;
500
501 GrIRect viewport;
502
503 // viewport is in GL coords (top >= bottom)
504 viewport.setLTRB(0, height, width, 0);
505
506 rtIDs.fRTFBOID = (GLuint)platformRenderTarget;
507 rtIDs.fTexFBOID = (GLuint)platformRenderTarget;
508
509 GrGLRenderTarget* rt = new GrGLRenderTarget(rtIDs, viewport, NULL, this);
510
511 return rt;
512}
513
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000514GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000515
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000516 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000517
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000518 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&rtIDs.fRTFBOID);
519 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
520 rtIDs.fMSColorRenderbufferID = 0;
521 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000522
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000523 GLint vp[4];
524 GR_GL_GetIntegerv(GL_VIEWPORT, vp);
525 GrIRect viewportRect;
526 viewportRect.setLTRB(vp[0],
527 vp[1] + vp[3],
528 vp[0] + vp[2],
529 vp[1]);
530 rtIDs.fOwnIDs = false;
531
532 return new GrGLRenderTarget(rtIDs,
533 viewportRect,
534 NULL,
535 this);
536}
537
bsalomon@google.com5782d712011-01-21 21:03:59 +0000538///////////////////////////////////////////////////////////////////////////////
539
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000540// defines stencil formats from more to less preferred
reed@google.com63100f92011-01-18 21:32:14 +0000541GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = {
542 GR_STENCIL_INDEX8,
543
544#if GR_SUPPORT_GLDESKTOP
545 GR_STENCIL_INDEX16,
546#endif
547
548 GR_DEPTH24_STENCIL8,
549 GR_STENCIL_INDEX4,
550
551#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000552 GL_STENCIL_INDEX,
553 GR_DEPTH_STENCIL,
554#endif
555};
556
557// good to set a break-point here to know when createTexture fails
558static GrTexture* return_null_texture() {
559// GrAssert(!"null texture");
560 return NULL;
561}
562
563#if GR_DEBUG
564static size_t as_size_t(int x) {
565 return x;
566}
567#endif
568
reed@google.comac10a2d2010-12-22 21:39:39 +0000569GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
570 const void* srcData, size_t rowBytes) {
571
572#if GR_COLLECT_STATS
573 ++fStats.fTextureCreateCnt;
574#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000575
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000576 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000577
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000578 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
579 GL_NEAREST,
580 GL_CLAMP_TO_EDGE,
581 GL_CLAMP_TO_EDGE
582 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000583
reed@google.comac10a2d2010-12-22 21:39:39 +0000584 GrGLTexture::GLTextureDesc glDesc;
585 GLenum internalFormat;
586
587 glDesc.fContentWidth = desc.fWidth;
588 glDesc.fContentHeight = desc.fHeight;
589 glDesc.fAllocWidth = desc.fWidth;
590 glDesc.fAllocHeight = desc.fHeight;
591 glDesc.fFormat = desc.fFormat;
592
593 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
594 if (!canBeTexture(desc.fFormat,
595 &internalFormat,
596 &glDesc.fUploadFormat,
597 &glDesc.fUploadType)) {
598 return return_null_texture();
599 }
600
601 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
602 GLint samples = fAASamples[desc.fAALevel];
603 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
604 GrPrintf("AA RT requested but not supported on this platform.");
605 }
606
607 GR_GL(GenTextures(1, &glDesc.fTextureID));
608 if (!glDesc.fTextureID) {
609 return return_null_texture();
610 }
611
612 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
613
614 /*
615 * check if our srcData has extra bytes past each row. If so, we need
616 * to trim those off here, since GL doesn't let us pass the rowBytes as
617 * a parameter to glTexImage2D
618 */
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000619#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000620 if (srcData) {
621 GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH,
622 rowBytes / glDesc.fUploadByteCount));
623 }
624#else
625 GrAutoSMalloc<128 * 128> trimStorage;
626 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
627 if (srcData && (trimRowBytes < rowBytes)) {
628 size_t trimSize = desc.fHeight * trimRowBytes;
629 trimStorage.realloc(trimSize);
630 // now copy the data into our new storage, skipping the trailing bytes
631 const char* src = (const char*)srcData;
632 char* dst = (char*)trimStorage.get();
633 for (uint32_t y = 0; y < desc.fHeight; y++) {
634 memcpy(dst, src, trimRowBytes);
635 src += rowBytes;
636 dst += trimRowBytes;
637 }
638 // now point srcData to our trimmed version
639 srcData = trimStorage.get();
640 }
641#endif
642
reed@google.comac10a2d2010-12-22 21:39:39 +0000643 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000644 if (!this->npotRenderTargetSupport()) {
645 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
646 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
647 }
648
reed@google.comac10a2d2010-12-22 21:39:39 +0000649 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
650 glDesc.fAllocWidth);
651 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
652 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000653 } else if (!this->npotTextureSupport()) {
654 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
655 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000656 }
657
658 GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000659 GR_GL(TexParameteri(GL_TEXTURE_2D,
660 GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000661 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000662 GR_GL(TexParameteri(GL_TEXTURE_2D,
663 GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000664 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000665 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000666 GL_TEXTURE_WRAP_S,
667 DEFAULT_PARAMS.fWrapS));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000668 GR_GL(TexParameteri(GL_TEXTURE_2D,
669 GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000670 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000671
672 GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
673 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
674 supports8BitPalette()) {
675 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
676 GrAssert(desc.fWidth == glDesc.fAllocWidth);
677 GrAssert(desc.fHeight == glDesc.fAllocHeight);
678 GLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
679 kColorTableSize;
680 GR_GL(CompressedTexImage2D(GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
681 glDesc.fAllocWidth, glDesc.fAllocHeight,
682 0, imageSize, srcData));
683 GrGL_RestoreResetRowLength();
684 } else {
685 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
686 glDesc.fAllocHeight != desc.fHeight)) {
687 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat,
688 glDesc.fAllocWidth, glDesc.fAllocHeight,
689 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
690 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
691 desc.fHeight, glDesc.fUploadFormat,
692 glDesc.fUploadType, srcData));
693 GrGL_RestoreResetRowLength();
694
695 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
696 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
697 uint32_t maxTexels = extraW * extraH;
698 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
699 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
700
701 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
702
703 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
704 if (extraH) {
705 uint8_t* lastRowStart = (uint8_t*) srcData +
706 (desc.fHeight - 1) * rowSize;
707 uint8_t* extraRowStart = (uint8_t*)texels.get();
708
709 for (uint32_t i = 0; i < extraH; ++i) {
710 memcpy(extraRowStart, lastRowStart, rowSize);
711 extraRowStart += rowSize;
712 }
713 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
714 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
715 texels.get()));
716 }
717 if (extraW) {
718 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
719 uint8_t* extraTexel = (uint8_t*)texels.get();
720 for (uint32_t j = 0; j < desc.fHeight; ++j) {
721 for (uint32_t i = 0; i < extraW; ++i) {
722 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
723 extraTexel += glDesc.fUploadByteCount;
724 }
725 edgeTexel += rowSize;
726 }
727 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
728 desc.fHeight, glDesc.fUploadFormat,
729 glDesc.fUploadType, texels.get()));
730 }
731 if (extraW && extraH) {
732 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
733 - glDesc.fUploadByteCount;
734 uint8_t* extraTexel = (uint8_t*)texels.get();
735 for (uint32_t i = 0; i < extraW*extraH; ++i) {
736 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
737 extraTexel += glDesc.fUploadByteCount;
738 }
739 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
740 extraW, extraH, glDesc.fUploadFormat,
741 glDesc.fUploadType, texels.get()));
742 }
743
744 } else {
745 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
746 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
747 glDesc.fUploadType, srcData));
748 GrGL_RestoreResetRowLength();
749 }
750 }
751
752 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
753
754 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
755 rtIDs.fStencilRenderbufferID = 0;
756 rtIDs.fMSColorRenderbufferID = 0;
757 rtIDs.fRTFBOID = 0;
758 rtIDs.fTexFBOID = 0;
759 rtIDs.fOwnIDs = true;
760 GLenum msColorRenderbufferFormat = -1;
761
762 if (renderTarget) {
763#if GR_COLLECT_STATS
764 ++fStats.fRenderTargetCreateCnt;
765#endif
766 bool failed = true;
767 GLenum status;
768 GLint err;
769
770 // If need have both RT flag and srcData we have
771 // to invert the data before uploading because FBO
772 // will be rendered bottom up
773 GrAssert(NULL == srcData);
774 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
775
776 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fTexFBOID));
777 GrAssert(rtIDs.fTexFBOID);
778
779 // If we are using multisampling and any extension other than the IMG
780 // one we will create two FBOs. We render to one and then resolve to
781 // the texture bound to the other. The IMG extension does an implicit
782 // resolve.
783 if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
784 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fRTFBOID));
785 GrAssert(0 != rtIDs.fRTFBOID);
786 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
787 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
788 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
789 GR_GLEXT(fExts,
790 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
791 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
792 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
793 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000794 return return_null_texture();
795 }
796 } else {
797 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
798 }
799 int attempts = 1;
800 if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
801 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
802 GrAssert(0 != rtIDs.fStencilRenderbufferID);
803 attempts = GR_ARRAY_COUNT(GR_GL_STENCIL_FORMAT_ARRAY);
804 }
805
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000806 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000807 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000808 // (seems unlikely)
reed@google.comac10a2d2010-12-22 21:39:39 +0000809 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000810
811 err = ~GL_NO_ERROR;
812 for (int i = 0; i < attempts; ++i) {
813 if (rtIDs.fStencilRenderbufferID) {
814 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
815 rtIDs.fStencilRenderbufferID));
816 if (samples > 1) {
817 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
818 GR_RENDERBUFFER,
819 samples,
820 GR_GL_STENCIL_FORMAT_ARRAY[i],
821 glDesc.fAllocWidth,
822 glDesc.fAllocHeight));
823 } else {
824 GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
825 GR_RENDERBUFFER,
826 GR_GL_STENCIL_FORMAT_ARRAY[i],
827 glDesc.fAllocWidth,
828 glDesc.fAllocHeight));
829 }
830 err = glGetError();
831 if (err != GL_NO_ERROR) {
832 continue;
833 }
834 }
835 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
836 GrAssert(samples > 1);
837 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
838 rtIDs.fMSColorRenderbufferID));
839 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
840 GR_RENDERBUFFER,
841 samples,
842 msColorRenderbufferFormat,
843 glDesc.fAllocWidth,
844 glDesc.fAllocHeight));
845 err = glGetError();
846 if (err != GL_NO_ERROR) {
847 continue;
848 }
849 }
850 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
851
852#if GR_COLLECT_STATS
853 ++fStats.fRenderTargetChngCnt;
854#endif
855 if (kIMG_MSFBO == fMSFBOType && samples > 1) {
856 GR_GLEXT(fExts, FramebufferTexture2DMultisample(
857 GR_FRAMEBUFFER,
858 GR_COLOR_ATTACHMENT0,
859 GL_TEXTURE_2D,
860 glDesc.fTextureID,
861 0,
862 samples));
863
864 } else {
865 GR_GLEXT(fExts, FramebufferTexture2D(GR_FRAMEBUFFER,
866 GR_COLOR_ATTACHMENT0,
867 GL_TEXTURE_2D,
868 glDesc.fTextureID, 0));
869 }
870 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
871 GLenum status = GR_GLEXT(fExts,
872 CheckFramebufferStatus(GR_FRAMEBUFFER));
873 if (status != GR_FRAMEBUFFER_COMPLETE) {
874 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
875 status, desc.fWidth, desc.fHeight);
876 continue;
877 }
878 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
879 #if GR_COLLECT_STATS
880 ++fStats.fRenderTargetChngCnt;
881 #endif
882 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
883 GR_COLOR_ATTACHMENT0,
884 GR_RENDERBUFFER,
885 rtIDs.fMSColorRenderbufferID));
886
887 }
888 if (rtIDs.fStencilRenderbufferID) {
889 // bind the stencil to rt fbo if present, othewise the tex fbo
890 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
891 GR_STENCIL_ATTACHMENT,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000892 GR_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000893 rtIDs.fStencilRenderbufferID));
894 }
895 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
896
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000897#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000898 // On some implementations you have to be bound as DEPTH_STENCIL.
899 // (Even binding to DEPTH and STENCIL separately with the same
900 // buffer doesn't work.)
901 if (rtIDs.fStencilRenderbufferID &&
902 status != GR_FRAMEBUFFER_COMPLETE) {
903 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
904 GR_STENCIL_ATTACHMENT,
905 GR_RENDERBUFFER,
906 0));
907 GR_GLEXT(fExts,
908 FramebufferRenderbuffer(GR_FRAMEBUFFER,
909 GR_DEPTH_STENCIL_ATTACHMENT,
910 GR_RENDERBUFFER,
911 rtIDs.fStencilRenderbufferID));
912 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
913 }
914#endif
915 if (status != GR_FRAMEBUFFER_COMPLETE) {
916 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
917 status, desc.fWidth, desc.fHeight);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000918#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000919 if (rtIDs.fStencilRenderbufferID) {
920 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
921 GR_DEPTH_STENCIL_ATTACHMENT,
922 GR_RENDERBUFFER,
923 0));
924 }
925#endif
926 continue;
927 }
928 // we're successful!
929 failed = false;
930 break;
931 }
932 if (failed) {
933 if (rtIDs.fStencilRenderbufferID) {
934 GR_GLEXT(fExts,
935 DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
936 }
937 if (rtIDs.fMSColorRenderbufferID) {
938 GR_GLEXT(fExts,
939 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
940 }
941 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
942 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
943 }
944 if (rtIDs.fTexFBOID) {
945 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
946 }
947 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
948 return return_null_texture();
949 }
950 }
951#ifdef TRACE_TEXTURE_CREATION
952 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
953 tex->fTextureID, width, height, tex->fUploadByteCount);
954#endif
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000955 GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, DEFAULT_PARAMS, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000956
957 if (0 != rtIDs.fTexFBOID) {
958 GrRenderTarget* rt = tex->asRenderTarget();
959 // We've messed with FBO state but may not have set the correct viewport
960 // so just dirty the rendertarget state to force a resend.
961 fHWDrawState.fRenderTarget = NULL;
962
963 // clear the new stencil buffer if we have one
964 if (!(desc.fFlags & kNoPathRendering_TextureFlag)) {
965 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
966 fCurrDrawState.fRenderTarget = rt;
967 eraseStencil(0, ~0);
968 fCurrDrawState.fRenderTarget = rtSave;
969 }
970 }
971 return tex;
972}
973
reed@google.comac10a2d2010-12-22 21:39:39 +0000974GrVertexBuffer* GrGpuGL::createVertexBuffer(uint32_t size, bool dynamic) {
975 GLuint id;
976 GR_GL(GenBuffers(1, &id));
977 if (id) {
978 GR_GL(BindBuffer(GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000979 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000980 GrGLClearErr();
981 // make sure driver can allocate memory for this buffer
982 GR_GL_NO_ERR(BufferData(GL_ARRAY_BUFFER, size, NULL,
983 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
984 if (glGetError() != GL_NO_ERROR) {
985 GR_GL(DeleteBuffers(1, &id));
986 // deleting bound buffer does implicit bind to 0
987 fHWGeometryState.fVertexBuffer = NULL;
988 return NULL;
989 }
990 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this,
991 size, dynamic);
992 fHWGeometryState.fVertexBuffer = vertexBuffer;
993 return vertexBuffer;
994 }
995 return NULL;
996}
997
998GrIndexBuffer* GrGpuGL::createIndexBuffer(uint32_t size, bool dynamic) {
999 GLuint id;
1000 GR_GL(GenBuffers(1, &id));
1001 if (id) {
1002 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, id));
1003 GrGLClearErr();
1004 // make sure driver can allocate memory for this buffer
1005 GR_GL_NO_ERR(BufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1006 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
1007 if (glGetError() != GL_NO_ERROR) {
1008 GR_GL(DeleteBuffers(1, &id));
1009 // deleting bound buffer does implicit bind to 0
1010 fHWGeometryState.fIndexBuffer = NULL;
1011 return NULL;
1012 }
1013 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this,
1014 size, dynamic);
1015 fHWGeometryState.fIndexBuffer = indexBuffer;
1016 return indexBuffer;
1017 }
1018 return NULL;
1019}
1020
reed@google.comac10a2d2010-12-22 21:39:39 +00001021void GrGpuGL::flushScissor(const GrIRect* rect) {
1022 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1023 const GrIRect& vp =
1024 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1025
1026 if (NULL != rect &&
1027 rect->contains(vp)) {
1028 rect = NULL;
1029 }
1030
1031 if (NULL != rect) {
1032 GrIRect scissor;
1033 // viewport is already in GL coords
1034 // create a scissor in GL coords (top > bottom)
1035 scissor.setLTRB(vp.fLeft + rect->fLeft,
1036 vp.fTop - rect->fTop,
1037 vp.fLeft + rect->fRight,
1038 vp.fTop - rect->fBottom);
1039
1040 if (fHWBounds.fScissorRect != scissor) {
1041 GR_GL(Scissor(scissor.fLeft, scissor.fBottom,
1042 scissor.width(), -scissor.height()));
1043 fHWBounds.fScissorRect = scissor;
1044 }
1045
1046 if (!fHWBounds.fScissorEnabled) {
1047 GR_GL(Enable(GL_SCISSOR_TEST));
1048 fHWBounds.fScissorEnabled = true;
1049 }
1050 } else {
1051 if (fHWBounds.fScissorEnabled) {
1052 GR_GL(Disable(GL_SCISSOR_TEST));
1053 fHWBounds.fScissorEnabled = false;
1054 }
1055 }
1056}
1057
reed@google.comac10a2d2010-12-22 21:39:39 +00001058void GrGpuGL::eraseColor(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001059 if (NULL == fCurrDrawState.fRenderTarget) {
1060 return;
1061 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001062 flushRenderTarget();
1063 if (fHWBounds.fScissorEnabled) {
1064 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001065 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001066 }
1067 GR_GL(ColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE));
1068 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1069 GrColorUnpackG(color)/255.f,
1070 GrColorUnpackB(color)/255.f,
1071 GrColorUnpackA(color)/255.f));
1072 GR_GL(Clear(GL_COLOR_BUFFER_BIT));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001073 fDirtyFlags.fWriteMaskChanged = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001074}
1075
1076void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001077 if (NULL == fCurrDrawState.fRenderTarget) {
1078 return;
1079 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001080 flushRenderTarget();
1081 if (fHWBounds.fScissorEnabled) {
1082 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001083 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001084 }
1085 GR_GL(StencilMask(mask));
1086 GR_GL(ClearStencil(value));
1087 GR_GL(Clear(GL_STENCIL_BUFFER_BIT));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001088 fDirtyFlags.fWriteMaskChanged = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001089}
1090
1091void GrGpuGL::eraseStencilClip() {
1092 GLint stencilBitCount;
reed@google.comac20fb92011-01-12 17:14:53 +00001093 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 GrAssert(stencilBitCount > 0);
1095 GLint clipStencilMask = (1 << (stencilBitCount - 1));
1096 eraseStencil(0, clipStencilMask);
1097}
1098
1099void GrGpuGL::forceRenderTargetFlush() {
1100 flushRenderTarget();
1101}
1102
1103bool GrGpuGL::readPixels(int left, int top, int width, int height,
1104 GrTexture::PixelConfig config, void* buffer) {
1105 GLenum internalFormat; // we don't use this for glReadPixels
1106 GLenum format;
1107 GLenum type;
1108 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1109 return false;
1110 }
1111
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001112 if (NULL == fCurrDrawState.fRenderTarget) {
1113 return false;
1114 }
1115 flushRenderTarget();
1116
reed@google.comac10a2d2010-12-22 21:39:39 +00001117 const GrIRect& vp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1118
1119 // Brian says that viewport rects are already upside down (grrrrr)
bsalomon@google.com316f99232011-01-13 21:28:12 +00001120 GR_GL(ReadPixels(left, -vp.height() - top - height, width, height,
1121 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001122
1123 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1124 // API presents top-to-bottom
1125 {
1126 size_t stride = width * GrTexture::BytesPerPixel(config);
1127 GrAutoMalloc rowStorage(stride);
1128 void* tmp = rowStorage.get();
1129
1130 const int halfY = height >> 1;
1131 char* top = reinterpret_cast<char*>(buffer);
1132 char* bottom = top + (height - 1) * stride;
1133 for (int y = 0; y < halfY; y++) {
1134 memcpy(tmp, top, stride);
1135 memcpy(top, bottom, stride);
1136 memcpy(bottom, tmp, stride);
1137 top += stride;
1138 bottom -= stride;
1139 }
1140 }
1141 return true;
1142}
1143
1144void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001145
1146 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1147
reed@google.comac10a2d2010-12-22 21:39:39 +00001148 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1149 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
1150 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
1151 #if GR_COLLECT_STATS
1152 ++fStats.fRenderTargetChngCnt;
1153 #endif
1154 rt->setDirty(true);
1155 #if GR_DEBUG
1156 GLenum status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
1157 if (status != GR_FRAMEBUFFER_COMPLETE) {
1158 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1159 }
1160 #endif
1161 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
1162 const GrIRect& vp = rt->viewport();
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001163 fDirtyFlags.fRenderTargetChanged = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001164 if (fHWBounds.fViewportRect != vp) {
1165 GR_GL(Viewport(vp.fLeft,
1166 vp.fBottom,
1167 vp.width(),
1168 -vp.height()));
1169 fHWBounds.fViewportRect = vp;
1170 }
1171 }
1172}
1173
1174GLenum gPrimitiveType2GLMode[] = {
1175 GL_TRIANGLES,
1176 GL_TRIANGLE_STRIP,
1177 GL_TRIANGLE_FAN,
1178 GL_POINTS,
1179 GL_LINES,
1180 GL_LINE_STRIP
1181};
1182
1183void GrGpuGL::drawIndexedHelper(PrimitiveType type,
1184 uint32_t startVertex,
1185 uint32_t startIndex,
1186 uint32_t vertexCount,
1187 uint32_t indexCount) {
1188 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1189
1190 GLvoid* indices = (GLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001191
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001192 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1193 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1194
1195 // our setupGeometry better have adjusted this to zero since
1196 // DrawElements always draws from the begining of the arrays for idx 0.
1197 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001198
1199 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1200 GL_UNSIGNED_SHORT, indices));
1201}
1202
1203void GrGpuGL::drawNonIndexedHelper(PrimitiveType type,
1204 uint32_t startVertex,
1205 uint32_t vertexCount) {
1206 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1207
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001208 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1209
1210 // our setupGeometry better have adjusted this to zero.
1211 // DrawElements doesn't take an offset so we always adjus the startVertex.
1212 GrAssert(0 == startVertex);
1213
1214 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1215 // account for startVertex in the DrawElements case. So we always
1216 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001217 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1218}
1219
reed@google.comac10a2d2010-12-22 21:39:39 +00001220void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1221 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1222
1223 if (NULL != rt && rt->needsResolve()) {
1224 GrAssert(kNone_MSFBO != fMSFBOType);
1225 GrAssert(rt->textureFBOID() != rt->renderFBOID());
1226 GR_GLEXT(fExts, BindFramebuffer(GR_READ_FRAMEBUFFER,
1227 rt->renderFBOID()));
1228 GR_GLEXT(fExts, BindFramebuffer(GR_DRAW_FRAMEBUFFER,
1229 rt->textureFBOID()));
1230 #if GR_COLLECT_STATS
1231 ++fStats.fRenderTargetChngCnt;
1232 #endif
1233 // make sure we go through set render target
1234 fHWDrawState.fRenderTarget = NULL;
1235
1236 GLint left = 0;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001237 GLint right = texture->width();
reed@google.comac10a2d2010-12-22 21:39:39 +00001238 // we will have rendered to the top of the FBO.
1239 GLint top = texture->allocHeight();
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001240 GLint bottom = texture->allocHeight() - texture->height();
reed@google.comac10a2d2010-12-22 21:39:39 +00001241 if (kApple_MSFBO == fMSFBOType) {
1242 GR_GL(Enable(GL_SCISSOR_TEST));
1243 GR_GL(Scissor(left, bottom, right-left, top-bottom));
1244 GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
1245 fHWBounds.fScissorRect.setEmpty();
1246 fHWBounds.fScissorEnabled = true;
1247 } else {
1248 GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
1249 left, bottom, right, top,
1250 GL_COLOR_BUFFER_BIT, GL_NEAREST));
1251 }
1252 rt->setDirty(false);
1253
1254 }
1255}
1256
1257void GrGpuGL::flushStencil() {
1258
1259 // use stencil for clipping if clipping is enabled and the clip
1260 // has been written into the stencil.
1261 bool stencilClip = fClipState.fClipInStencil &&
1262 (kClip_StateBit & fCurrDrawState.fFlagBits);
1263 bool stencilChange =
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001264 fDirtyFlags.fWriteMaskChanged ||
reed@google.comac10a2d2010-12-22 21:39:39 +00001265 fHWStencilClip != stencilClip ||
1266 fHWDrawState.fStencilPass != fCurrDrawState.fStencilPass ||
1267 (kNone_StencilPass != fCurrDrawState.fStencilPass &&
1268 (StencilPass)kSetClip_StencilPass != fCurrDrawState.fStencilPass &&
1269 fHWDrawState.fReverseFill != fCurrDrawState.fReverseFill);
1270
1271 if (stencilChange) {
1272 GLint stencilBitCount;
1273 GLint clipStencilMask;
1274 GLint pathStencilMask;
reed@google.comac20fb92011-01-12 17:14:53 +00001275 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001276 GrAssert(stencilBitCount > 0 ||
1277 kNone_StencilPass == fCurrDrawState.fStencilPass);
1278 clipStencilMask = (1 << (stencilBitCount - 1));
1279 pathStencilMask = clipStencilMask - 1;
1280 switch (fCurrDrawState.fStencilPass) {
1281 case kNone_StencilPass:
1282 if (stencilClip) {
1283 GR_GL(Enable(GL_STENCIL_TEST));
1284 GR_GL(StencilFunc(GL_EQUAL,
1285 clipStencilMask,
1286 clipStencilMask));
1287 GR_GL(StencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
1288 } else {
1289 GR_GL(Disable(GL_STENCIL_TEST));
1290 }
1291 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1292 if (!fSingleStencilPassForWinding) {
1293 GR_GL(Disable(GL_CULL_FACE));
1294 }
1295 break;
1296 case kEvenOddStencil_StencilPass:
1297 GR_GL(Enable(GL_STENCIL_TEST));
1298 if (stencilClip) {
1299 GR_GL(StencilFunc(GL_EQUAL, clipStencilMask, clipStencilMask));
1300 } else {
1301 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1302 }
1303 GR_GL(StencilMask(pathStencilMask));
1304 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1305 GR_GL(StencilOp(GL_KEEP, GL_INVERT, GL_INVERT));
1306 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1307 if (!fSingleStencilPassForWinding) {
1308 GR_GL(Disable(GL_CULL_FACE));
1309 }
1310 break;
1311 case kEvenOddColor_StencilPass: {
1312 GR_GL(Enable(GL_STENCIL_TEST));
1313 GLint funcRef = 0;
1314 GLuint funcMask = pathStencilMask;
1315 if (stencilClip) {
1316 funcRef |= clipStencilMask;
1317 funcMask |= clipStencilMask;
1318 }
1319 if (!fCurrDrawState.fReverseFill) {
1320 funcRef |= pathStencilMask;
1321 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001322
bsalomon@google.com316f99232011-01-13 21:28:12 +00001323 GR_GL(StencilFunc(GL_EQUAL, funcRef, funcMask));
1324 GR_GL(StencilMask(pathStencilMask));
reed@google.comac10a2d2010-12-22 21:39:39 +00001325 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1326 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1327 if (!fSingleStencilPassForWinding) {
1328 GR_GL(Disable(GL_CULL_FACE));
1329 }
1330 } break;
1331 case kWindingStencil1_StencilPass:
1332 GR_GL(Enable(GL_STENCIL_TEST));
1333 if (fHasStencilWrap) {
1334 if (stencilClip) {
1335 GR_GL(StencilFunc(GL_EQUAL,
1336 clipStencilMask,
1337 clipStencilMask));
1338 } else {
1339 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1340 }
1341 if (fSingleStencilPassForWinding) {
1342 GR_GL(StencilOpSeparate(GL_FRONT, GL_KEEP,
1343 GL_INCR_WRAP, GL_INCR_WRAP));
1344 GR_GL(StencilOpSeparate(GL_BACK, GL_KEEP,
1345 GL_DECR_WRAP, GL_DECR_WRAP));
1346 } else {
1347 GR_GL(StencilOp(GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP));
1348 GR_GL(Enable(GL_CULL_FACE));
1349 GR_GL(CullFace(GL_BACK));
1350 }
1351 } else {
1352 // If we don't have wrap then we use the Func to detect
1353 // values that would wrap (0 on decr and mask on incr). We
1354 // make the func fail on these values and use the sfail op
1355 // to effectively wrap by inverting.
1356 // This applies whether we are doing a two-pass (front faces
1357 // followed by back faces) or a single pass (separate func/op)
1358
1359 // Note that in the case where we are also using stencil to
1360 // clip this means we will write into the path bits in clipped
1361 // out pixels. We still apply the clip bit in the color pass
1362 // stencil func so we don't draw color outside the clip.
1363 // We also will clear the stencil bits in clipped pixels by
1364 // using zero in the sfail op with write mask set to the
1365 // path mask.
1366 GR_GL(Enable(GL_STENCIL_TEST));
1367 if (fSingleStencilPassForWinding) {
1368 GR_GL(StencilFuncSeparate(GL_FRONT,
1369 GL_NOTEQUAL,
1370 pathStencilMask,
1371 pathStencilMask));
1372 GR_GL(StencilFuncSeparate(GL_BACK,
1373 GL_NOTEQUAL,
1374 0x0,
1375 pathStencilMask));
1376 GR_GL(StencilOpSeparate(GL_FRONT, GL_INVERT,
1377 GL_INCR, GL_INCR));
1378 GR_GL(StencilOpSeparate(GL_BACK, GL_INVERT,
1379 GL_DECR, GL_DECR));
1380 } else {
1381 GR_GL(StencilFunc(GL_NOTEQUAL,
1382 pathStencilMask,
1383 pathStencilMask));
1384 GR_GL(StencilOp(GL_INVERT, GL_INCR, GL_INCR));
1385 GR_GL(Enable(GL_CULL_FACE));
1386 GR_GL(CullFace(GL_BACK));
1387 }
1388 }
1389 GR_GL(StencilMask(pathStencilMask));
1390 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1391 break;
1392 case kWindingStencil2_StencilPass:
1393 GrAssert(!fSingleStencilPassForWinding);
1394 GR_GL(Enable(GL_STENCIL_TEST));
1395 if (fHasStencilWrap) {
1396 if (stencilClip) {
1397 GR_GL(StencilFunc(GL_EQUAL,
1398 clipStencilMask,
1399 clipStencilMask));
1400 } else {
1401 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1402 }
1403 GR_GL(StencilOp(GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP));
1404 } else {
1405 GR_GL(StencilFunc(GL_NOTEQUAL, 0x0, pathStencilMask));
1406 GR_GL(StencilOp(GL_INVERT, GL_DECR, GL_DECR));
1407 }
1408 GR_GL(StencilMask(pathStencilMask));
1409 GR_GL(Enable(GL_CULL_FACE));
1410 GR_GL(CullFace(GL_FRONT));
1411 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1412 break;
1413 case kWindingColor_StencilPass: {
1414 GR_GL(Enable(GL_STENCIL_TEST));
1415 GLint funcRef = 0;
1416 GLuint funcMask = pathStencilMask;
1417 GLenum funcFunc;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001418
reed@google.comac10a2d2010-12-22 21:39:39 +00001419 if (stencilClip) {
1420 funcRef |= clipStencilMask;
1421 funcMask |= clipStencilMask;
1422 }
1423 if (fCurrDrawState.fReverseFill) {
1424 funcFunc = GL_EQUAL;
1425 } else {
1426 funcFunc = GL_LESS;
1427 }
1428 GR_GL(StencilFunc(funcFunc, funcRef, funcMask));
1429 GR_GL(StencilMask(pathStencilMask));
1430 // must zero in sfail because winding w/o wrap will write
1431 // path stencil bits in clipped out pixels
1432 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1433 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1434 if (!fSingleStencilPassForWinding) {
1435 GR_GL(Disable(GL_CULL_FACE));
1436 }
1437 } break;
1438 case kSetClip_StencilPass:
1439 GR_GL(Enable(GL_STENCIL_TEST));
1440 GR_GL(StencilFunc(GL_ALWAYS, clipStencilMask, clipStencilMask));
1441 GR_GL(StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
1442 GR_GL(StencilMask(clipStencilMask));
1443 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1444 if (!fSingleStencilPassForWinding) {
1445 GR_GL(Disable(GL_CULL_FACE));
1446 }
1447 break;
1448 default:
1449 GrAssert(!"Unexpected stencil pass.");
1450 break;
1451
1452 }
1453 fHWDrawState.fStencilPass = fCurrDrawState.fStencilPass;
1454 fHWDrawState.fReverseFill = fCurrDrawState.fReverseFill;
reed@google.comac10a2d2010-12-22 21:39:39 +00001455 fHWStencilClip = stencilClip;
1456 }
1457}
1458
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001459bool GrGpuGL::flushGLStateCommon(PrimitiveType type) {
1460
1461 // GrGpu::setupClipAndFlushState should have already checked this
1462 // and bailed if not true.
1463 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001464
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001465 for (int s = 0; s < kNumStages; ++s) {
1466 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001467
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001468 // bind texture and set sampler state
1469 if (usingTexture) {
1470 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001471
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001472 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001473 // if we created a rt/tex and rendered to it without using a
1474 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001475 // the last bound texture, but it needs resolving. So keep this
1476 // out of the "last != next" check.
1477 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001478
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001479 if (fHWDrawState.fTextures[s] != nextTexture) {
1480 setTextureUnit(s);
1481 GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
1482 #if GR_COLLECT_STATS
1483 ++fStats.fTextureChngCnt;
1484 #endif
1485 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1486 fHWDrawState.fTextures[s] = nextTexture;
1487 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001488
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001489 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001490 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001491 nextTexture->getTexParams();
1492 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001493
1494 newTexParams.fFilter = sampler.isFilter() ? GL_LINEAR :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001495 GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001496 newTexParams.fWrapS =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001497 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001498 newTexParams.fWrapT =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001499 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001500
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001501 if (newTexParams.fFilter != oldTexParams.fFilter) {
1502 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001503 GR_GL(TexParameteri(GL_TEXTURE_2D,
1504 GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001505 newTexParams.fFilter));
bsalomon@google.com316f99232011-01-13 21:28:12 +00001506 GR_GL(TexParameteri(GL_TEXTURE_2D,
1507 GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001508 newTexParams.fFilter));
1509 }
1510 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1511 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001512 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001513 GL_TEXTURE_WRAP_S,
1514 newTexParams.fWrapS));
1515 }
1516 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1517 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001518 GR_GL(TexParameteri(GL_TEXTURE_2D,
1519 GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001520 newTexParams.fWrapT));
1521 }
1522 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001523
1524 // The texture matrix has to compensate for texture width/height
1525 // and NPOT-embedded-in-POT
1526 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001527 } else {
1528 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001529 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001530 }
1531 }
1532 }
1533
1534 flushRenderTarget();
1535
1536 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1537 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1538 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
1539 GR_GL(Enable(GL_DITHER));
1540 } else {
1541 GR_GL(Disable(GL_DITHER));
1542 }
1543 }
1544
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001545#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +00001546 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1547 // smooth lines.
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001548 if (fDirtyFlags.fRenderTargetChanged ||
reed@google.comac10a2d2010-12-22 21:39:39 +00001549 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1550 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1551 GLint msaa = 0;
1552 // only perform query if we know MSAA is supported.
1553 // calling on non-MSAA target caused a crash in one environment,
1554 // though I don't think it should.
1555 if (!fAASamples[kHigh_AALevel]) {
reed@google.comac20fb92011-01-12 17:14:53 +00001556 GR_GL_GetIntegerv(GL_SAMPLE_BUFFERS, &msaa);
reed@google.comac10a2d2010-12-22 21:39:39 +00001557 }
1558 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1559 if (msaa) {
1560 GR_GL(Enable(GL_MULTISAMPLE));
1561 } else {
1562 GR_GL(Enable(GL_LINE_SMOOTH));
1563 }
1564 } else {
1565 if (msaa) {
1566 GR_GL(Disable(GL_MULTISAMPLE));
1567 }
1568 GR_GL(Disable(GL_LINE_SMOOTH));
1569 }
1570 }
1571#endif
1572
1573 bool blendOff = canDisableBlend();
1574 if (fHWBlendDisabled != blendOff) {
1575 if (blendOff) {
1576 GR_GL(Disable(GL_BLEND));
1577 } else {
1578 GR_GL(Enable(GL_BLEND));
1579 }
1580 fHWBlendDisabled = blendOff;
1581 }
1582
1583 if (!blendOff) {
1584 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1585 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1586 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1587 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1588 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1589 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1590 }
1591 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001592
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001593#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001594 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001595 for (int s = 0; s < kNumStages; ++s) {
1596 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1597 NULL == fCurrDrawState.fRenderTarget ||
1598 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001599 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001600 fCurrDrawState.fRenderTarget);
1601 }
1602#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001603
reed@google.comac10a2d2010-12-22 21:39:39 +00001604 flushStencil();
1605
1606 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001607 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001608}
1609
1610void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001611 if (fHWGeometryState.fVertexBuffer != buffer) {
1612 fHWGeometryState.fArrayPtrsDirty = true;
1613 fHWGeometryState.fVertexBuffer = buffer;
1614 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001615}
1616
1617void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1618 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1619 buffer == fGeometrySrc.fVertexBuffer));
1620
1621 if (fHWGeometryState.fVertexBuffer == buffer) {
1622 // deleting bound buffer does implied bind to 0
1623 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001624 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001625 }
1626}
1627
1628void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1629 fGeometrySrc.fIndexBuffer = buffer;
1630}
1631
1632void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1633 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1634 buffer == fGeometrySrc.fIndexBuffer));
1635
1636 if (fHWGeometryState.fIndexBuffer == buffer) {
1637 // deleting bound buffer does implied bind to 0
1638 fHWGeometryState.fIndexBuffer = NULL;
1639 }
1640}
1641
reed@google.comac10a2d2010-12-22 21:39:39 +00001642void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1643 GrAssert(NULL != renderTarget);
1644
1645 // if the bound FBO is destroyed we can't rely on the implicit bind to 0
1646 // a) we want the default RT which may not be FBO 0
1647 // b) we set more state than just FBO based on the RT
1648 // So trash the HW state to force an RT flush next time
1649 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001650 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001651 }
1652 if (fHWDrawState.fRenderTarget == renderTarget) {
1653 fHWDrawState.fRenderTarget = NULL;
1654 }
1655 if (fClipState.fStencilClipTarget == renderTarget) {
1656 fClipState.fStencilClipTarget = NULL;
1657 }
1658}
1659
1660void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001661 for (int s = 0; s < kNumStages; ++s) {
1662 if (fCurrDrawState.fTextures[s] == texture) {
1663 fCurrDrawState.fTextures[s] = NULL;
1664 }
1665 if (fHWDrawState.fTextures[s] == texture) {
1666 // deleting bound texture does implied bind to 0
1667 fHWDrawState.fTextures[s] = NULL;
1668 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001669 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001670}
1671
1672void GrGpuGL::notifyTextureRemoveRenderTarget(GrGLTexture* texture) {
1673 GrAssert(NULL != texture->asRenderTarget());
1674
1675 // if there is a pending resolve, perform it.
1676 resolveTextureRenderTarget(texture);
1677}
1678
1679bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
1680 GLenum* internalFormat,
1681 GLenum* format,
1682 GLenum* type) {
1683 switch (config) {
1684 case GrTexture::kRGBA_8888_PixelConfig:
1685 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001686 *format = GR_GL_32BPP_COLOR_FORMAT;
reed@google.com63100f92011-01-18 21:32:14 +00001687#if GR_SUPPORT_GLES
1688 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1689 // format for a BGRA is BGRA not RGBA (as on desktop)
1690 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1691#else
1692 *internalFormat = GL_RGBA;
bsalomon@google.comed3a0682011-01-18 16:54:04 +00001693#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001694 *type = GL_UNSIGNED_BYTE;
1695 break;
1696 case GrTexture::kRGB_565_PixelConfig:
1697 *format = GL_RGB;
1698 *internalFormat = GL_RGB;
1699 *type = GL_UNSIGNED_SHORT_5_6_5;
1700 break;
1701 case GrTexture::kRGBA_4444_PixelConfig:
1702 *format = GL_RGBA;
1703 *internalFormat = GL_RGBA;
1704 *type = GL_UNSIGNED_SHORT_4_4_4_4;
1705 break;
1706 case GrTexture::kIndex_8_PixelConfig:
1707 if (this->supports8BitPalette()) {
1708 *format = GR_PALETTE8_RGBA8;
1709 *internalFormat = GR_PALETTE8_RGBA8;
1710 *type = GL_UNSIGNED_BYTE; // unused I think
1711 } else {
1712 return false;
1713 }
1714 break;
1715 case GrTexture::kAlpha_8_PixelConfig:
1716 *format = GL_ALPHA;
1717 *internalFormat = GL_ALPHA;
1718 *type = GL_UNSIGNED_BYTE;
1719 break;
1720 default:
1721 return false;
1722 }
1723 return true;
1724}
1725
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001726void GrGpuGL::setTextureUnit(int unit) {
1727 GrAssert(unit >= 0 && unit < kNumStages);
1728 if (fActiveTextureUnitIdx != unit) {
1729 GR_GL(ActiveTexture(GL_TEXTURE0 + unit));
1730 fActiveTextureUnitIdx = unit;
1731 }
1732}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001733
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001734void GrGpuGL::setSpareTextureUnit() {
1735 if (fActiveTextureUnitIdx != (GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1736 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
1737 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1738 }
1739}
1740
reed@google.comac10a2d2010-12-22 21:39:39 +00001741/* On ES the internalFormat and format must match for TexImage and we use
1742 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1743 decide the internalFormat. However, on ES internalFormat for
1744 RenderBufferStorage* has to be a specific format (not a base format like
1745 GL_RGBA).
1746 */
1747bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) {
1748 switch (config) {
1749 case GrTexture::kRGBA_8888_PixelConfig:
1750 case GrTexture::kRGBX_8888_PixelConfig:
1751 if (fRGBA8Renderbuffer) {
1752 *format = GR_RGBA8;
1753 return true;
1754 } else {
1755 return false;
1756 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001757#if GR_SUPPORT_GLES // ES2 supports 565. ES1 supports it with FBO extension
1758 // desktop GL has no such internal format
reed@google.comac10a2d2010-12-22 21:39:39 +00001759 case GrTexture::kRGB_565_PixelConfig:
1760 *format = GR_RGB565;
1761 return true;
1762#endif
1763 case GrTexture::kRGBA_4444_PixelConfig:
1764 *format = GL_RGBA4;
1765 return true;
1766 default:
1767 return false;
1768 }
1769}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001770
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001771void GrGpuGL::resetDirtyFlags() {
1772 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1773}
1774
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001775void GrGpuGL::setBuffers(bool indexed,
1776 int* extraVertexOffset,
1777 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001778
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001779 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001780
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001781 GrGLVertexBuffer* vbuf;
1782 switch (fGeometrySrc.fVertexSrc) {
1783 case kBuffer_GeometrySrcType:
1784 *extraVertexOffset = 0;
1785 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1786 break;
1787 case kArray_GeometrySrcType:
1788 case kReserved_GeometrySrcType:
1789 finalizeReservedVertices();
1790 *extraVertexOffset = fCurrPoolStartVertex;
1791 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1792 break;
1793 default:
1794 vbuf = NULL; // suppress warning
1795 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001796 }
1797
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001798 GrAssert(NULL != vbuf);
1799 GrAssert(!vbuf->isLocked());
1800 if (fHWGeometryState.fVertexBuffer != vbuf) {
1801 GR_GL(BindBuffer(GL_ARRAY_BUFFER, vbuf->bufferID()));
1802 fHWGeometryState.fArrayPtrsDirty = true;
1803 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001804 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001805
1806 if (indexed) {
1807 GrAssert(NULL != extraIndexOffset);
1808
1809 GrGLIndexBuffer* ibuf;
1810 switch (fGeometrySrc.fIndexSrc) {
1811 case kBuffer_GeometrySrcType:
1812 *extraIndexOffset = 0;
1813 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1814 break;
1815 case kArray_GeometrySrcType:
1816 case kReserved_GeometrySrcType:
1817 finalizeReservedIndices();
1818 *extraIndexOffset = fCurrPoolStartIndex;
1819 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1820 break;
1821 default:
1822 ibuf = NULL; // suppress warning
1823 GrCrash("Unknown geometry src type!");
1824 }
1825
1826 GrAssert(NULL != ibuf);
1827 GrAssert(!ibuf->isLocked());
1828 if (fHWGeometryState.fIndexBuffer != ibuf) {
1829 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
1830 fHWGeometryState.fIndexBuffer = ibuf;
1831 }
1832 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001833}