blob: b30dd027cf88627ae7b00bb0b85d83ec902ece8e [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
bsalomon@google.comffca4002011-02-22 20:34:01 +0000446 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
447 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000448 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
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000461 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000462 fHWBounds.fScissorEnabled = false;
463 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000464 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000465
reed@google.comac10a2d2010-12-22 21:39:39 +0000466 // disabling the stencil test also disables
467 // stencil buffer writes
468 GR_GL(Disable(GL_STENCIL_TEST));
469 GR_GL(StencilMask(0xffffffff));
470 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
471 fHWDrawState.fReverseFill = false;
472 fHWDrawState.fStencilPass = kNone_StencilPass;
473 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000474 fClipState.fClipIsDirty = true;
475 fClipState.fStencilClipTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000476
477 fHWGeometryState.fIndexBuffer = NULL;
478 fHWGeometryState.fVertexBuffer = NULL;
479 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
480 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000481 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000482
483 fHWDrawState.fRenderTarget = NULL;
484}
485
486void GrGpuGL::resetContext() {
487 INHERITED::resetContext();
488 resetContextHelper();
489}
490
reed@google.comac10a2d2010-12-22 21:39:39 +0000491GrRenderTarget* GrGpuGL::createPlatformRenderTarget(
492 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000493 int stencilBits,
494 int width,
495 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000496 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
497 rtIDs.fStencilRenderbufferID = 0;
498 rtIDs.fMSColorRenderbufferID = 0;
499 rtIDs.fTexFBOID = 0;
500 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000501 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000502
503 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000504 viewport.fLeft = 0;
505 viewport.fBottom = 0;
506 viewport.fWidth = width;
507 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000508
509 rtIDs.fRTFBOID = (GLuint)platformRenderTarget;
510 rtIDs.fTexFBOID = (GLuint)platformRenderTarget;
511
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000512 return new GrGLRenderTarget(rtIDs, stencilBits, viewport, NULL, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000513}
514
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000515GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000516
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000517 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000518
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000519 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&rtIDs.fRTFBOID);
520 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
521 rtIDs.fMSColorRenderbufferID = 0;
522 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000523
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000524 GrGLIRect viewport;
525 viewport.setFromGLViewport();
526 GLuint stencilBits;
527 GR_GL_GetIntegerv(GL_STENCIL_BITS, (GLint*)&stencilBits);
528
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000529 rtIDs.fOwnIDs = false;
530
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000531 return new GrGLRenderTarget(rtIDs, stencilBits, viewport, NULL, this);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000532}
533
bsalomon@google.com5782d712011-01-21 21:03:59 +0000534///////////////////////////////////////////////////////////////////////////////
535
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000536static const GLuint UNKNOWN_BITS = ~0;
537
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000538// defines stencil formats from more to less preferred
bsalomon@google.com5d18c382011-02-18 16:21:58 +0000539static const struct {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000540 GLenum fEnum;
541 GLuint fBits;
542} gStencilFormats[] = {
543 {GR_STENCIL_INDEX8, 8},
reed@google.com63100f92011-01-18 21:32:14 +0000544
545#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000546 {GR_STENCIL_INDEX16, 16},
reed@google.com63100f92011-01-18 21:32:14 +0000547#endif
548
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000549 {GR_DEPTH24_STENCIL8, 8},
550 {GR_STENCIL_INDEX4, 4},
reed@google.com63100f92011-01-18 21:32:14 +0000551
552#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000553 {GL_STENCIL_INDEX, UNKNOWN_BITS},
554 {GR_DEPTH_STENCIL, UNKNOWN_BITS}
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000555#endif
556};
557
558// good to set a break-point here to know when createTexture fails
559static GrTexture* return_null_texture() {
560// GrAssert(!"null texture");
561 return NULL;
562}
563
564#if GR_DEBUG
565static size_t as_size_t(int x) {
566 return x;
567}
568#endif
569
reed@google.comac10a2d2010-12-22 21:39:39 +0000570GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
571 const void* srcData, size_t rowBytes) {
572
573#if GR_COLLECT_STATS
574 ++fStats.fTextureCreateCnt;
575#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000576
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000577 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000578
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000579 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
580 GL_NEAREST,
581 GL_CLAMP_TO_EDGE,
582 GL_CLAMP_TO_EDGE
583 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000584
reed@google.comac10a2d2010-12-22 21:39:39 +0000585 GrGLTexture::GLTextureDesc glDesc;
586 GLenum internalFormat;
587
588 glDesc.fContentWidth = desc.fWidth;
589 glDesc.fContentHeight = desc.fHeight;
590 glDesc.fAllocWidth = desc.fWidth;
591 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000592 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000593 glDesc.fFormat = desc.fFormat;
594
595 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
596 if (!canBeTexture(desc.fFormat,
597 &internalFormat,
598 &glDesc.fUploadFormat,
599 &glDesc.fUploadType)) {
600 return return_null_texture();
601 }
602
603 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
604 GLint samples = fAASamples[desc.fAALevel];
605 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
606 GrPrintf("AA RT requested but not supported on this platform.");
607 }
608
609 GR_GL(GenTextures(1, &glDesc.fTextureID));
610 if (!glDesc.fTextureID) {
611 return return_null_texture();
612 }
613
614 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
615
616 /*
617 * check if our srcData has extra bytes past each row. If so, we need
618 * to trim those off here, since GL doesn't let us pass the rowBytes as
619 * a parameter to glTexImage2D
620 */
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000621#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000622 if (srcData) {
623 GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH,
624 rowBytes / glDesc.fUploadByteCount));
625 }
626#else
627 GrAutoSMalloc<128 * 128> trimStorage;
628 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
629 if (srcData && (trimRowBytes < rowBytes)) {
630 size_t trimSize = desc.fHeight * trimRowBytes;
631 trimStorage.realloc(trimSize);
632 // now copy the data into our new storage, skipping the trailing bytes
633 const char* src = (const char*)srcData;
634 char* dst = (char*)trimStorage.get();
635 for (uint32_t y = 0; y < desc.fHeight; y++) {
636 memcpy(dst, src, trimRowBytes);
637 src += rowBytes;
638 dst += trimRowBytes;
639 }
640 // now point srcData to our trimmed version
641 srcData = trimStorage.get();
642 }
643#endif
644
reed@google.comac10a2d2010-12-22 21:39:39 +0000645 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000646 if (!this->npotRenderTargetSupport()) {
647 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
648 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
649 }
650
reed@google.comac10a2d2010-12-22 21:39:39 +0000651 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
652 glDesc.fAllocWidth);
653 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
654 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000655 } else if (!this->npotTextureSupport()) {
656 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
657 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000658 }
659
660 GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000661 GR_GL(TexParameteri(GL_TEXTURE_2D,
662 GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000663 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000664 GR_GL(TexParameteri(GL_TEXTURE_2D,
665 GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000666 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000667 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000668 GL_TEXTURE_WRAP_S,
669 DEFAULT_PARAMS.fWrapS));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000670 GR_GL(TexParameteri(GL_TEXTURE_2D,
671 GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000672 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000673
674 GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
675 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
676 supports8BitPalette()) {
677 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
678 GrAssert(desc.fWidth == glDesc.fAllocWidth);
679 GrAssert(desc.fHeight == glDesc.fAllocHeight);
680 GLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
681 kColorTableSize;
682 GR_GL(CompressedTexImage2D(GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
683 glDesc.fAllocWidth, glDesc.fAllocHeight,
684 0, imageSize, srcData));
685 GrGL_RestoreResetRowLength();
686 } else {
687 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
688 glDesc.fAllocHeight != desc.fHeight)) {
689 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat,
690 glDesc.fAllocWidth, glDesc.fAllocHeight,
691 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
692 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
693 desc.fHeight, glDesc.fUploadFormat,
694 glDesc.fUploadType, srcData));
695 GrGL_RestoreResetRowLength();
696
697 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
698 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
699 uint32_t maxTexels = extraW * extraH;
700 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
701 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
702
703 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
704
705 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
706 if (extraH) {
707 uint8_t* lastRowStart = (uint8_t*) srcData +
708 (desc.fHeight - 1) * rowSize;
709 uint8_t* extraRowStart = (uint8_t*)texels.get();
710
711 for (uint32_t i = 0; i < extraH; ++i) {
712 memcpy(extraRowStart, lastRowStart, rowSize);
713 extraRowStart += rowSize;
714 }
715 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
716 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
717 texels.get()));
718 }
719 if (extraW) {
720 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
721 uint8_t* extraTexel = (uint8_t*)texels.get();
722 for (uint32_t j = 0; j < desc.fHeight; ++j) {
723 for (uint32_t i = 0; i < extraW; ++i) {
724 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
725 extraTexel += glDesc.fUploadByteCount;
726 }
727 edgeTexel += rowSize;
728 }
729 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
730 desc.fHeight, glDesc.fUploadFormat,
731 glDesc.fUploadType, texels.get()));
732 }
733 if (extraW && extraH) {
734 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
735 - glDesc.fUploadByteCount;
736 uint8_t* extraTexel = (uint8_t*)texels.get();
737 for (uint32_t i = 0; i < extraW*extraH; ++i) {
738 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
739 extraTexel += glDesc.fUploadByteCount;
740 }
741 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
742 extraW, extraH, glDesc.fUploadFormat,
743 glDesc.fUploadType, texels.get()));
744 }
745
746 } else {
747 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
748 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
749 glDesc.fUploadType, srcData));
750 GrGL_RestoreResetRowLength();
751 }
752 }
753
754 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
755
756 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
757 rtIDs.fStencilRenderbufferID = 0;
758 rtIDs.fMSColorRenderbufferID = 0;
759 rtIDs.fRTFBOID = 0;
760 rtIDs.fTexFBOID = 0;
761 rtIDs.fOwnIDs = true;
762 GLenum msColorRenderbufferFormat = -1;
763
764 if (renderTarget) {
765#if GR_COLLECT_STATS
766 ++fStats.fRenderTargetCreateCnt;
767#endif
768 bool failed = true;
769 GLenum status;
770 GLint err;
771
772 // If need have both RT flag and srcData we have
773 // to invert the data before uploading because FBO
774 // will be rendered bottom up
775 GrAssert(NULL == srcData);
776 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
777
778 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fTexFBOID));
779 GrAssert(rtIDs.fTexFBOID);
780
781 // If we are using multisampling and any extension other than the IMG
782 // one we will create two FBOs. We render to one and then resolve to
783 // the texture bound to the other. The IMG extension does an implicit
784 // resolve.
785 if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
786 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fRTFBOID));
787 GrAssert(0 != rtIDs.fRTFBOID);
788 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
789 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
790 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
791 GR_GLEXT(fExts,
792 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
793 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
794 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
795 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000796 return return_null_texture();
797 }
798 } else {
799 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
800 }
801 int attempts = 1;
802 if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
803 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
804 GrAssert(0 != rtIDs.fStencilRenderbufferID);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000805 attempts = GR_ARRAY_COUNT(gStencilFormats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000806 }
807
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000808 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000809 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000810 // (seems unlikely)
reed@google.comac10a2d2010-12-22 21:39:39 +0000811 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000812
813 err = ~GL_NO_ERROR;
814 for (int i = 0; i < attempts; ++i) {
815 if (rtIDs.fStencilRenderbufferID) {
816 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
817 rtIDs.fStencilRenderbufferID));
818 if (samples > 1) {
819 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
820 GR_RENDERBUFFER,
821 samples,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000822 gStencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000823 glDesc.fAllocWidth,
824 glDesc.fAllocHeight));
825 } else {
826 GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
827 GR_RENDERBUFFER,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000828 gStencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000829 glDesc.fAllocWidth,
830 glDesc.fAllocHeight));
831 }
832 err = glGetError();
833 if (err != GL_NO_ERROR) {
834 continue;
835 }
836 }
837 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
838 GrAssert(samples > 1);
839 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
840 rtIDs.fMSColorRenderbufferID));
841 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
842 GR_RENDERBUFFER,
843 samples,
844 msColorRenderbufferFormat,
845 glDesc.fAllocWidth,
846 glDesc.fAllocHeight));
847 err = glGetError();
848 if (err != GL_NO_ERROR) {
849 continue;
850 }
851 }
852 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
853
854#if GR_COLLECT_STATS
855 ++fStats.fRenderTargetChngCnt;
856#endif
857 if (kIMG_MSFBO == fMSFBOType && samples > 1) {
858 GR_GLEXT(fExts, FramebufferTexture2DMultisample(
859 GR_FRAMEBUFFER,
860 GR_COLOR_ATTACHMENT0,
861 GL_TEXTURE_2D,
862 glDesc.fTextureID,
863 0,
864 samples));
865
866 } else {
867 GR_GLEXT(fExts, FramebufferTexture2D(GR_FRAMEBUFFER,
868 GR_COLOR_ATTACHMENT0,
869 GL_TEXTURE_2D,
870 glDesc.fTextureID, 0));
871 }
872 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
873 GLenum status = GR_GLEXT(fExts,
874 CheckFramebufferStatus(GR_FRAMEBUFFER));
875 if (status != GR_FRAMEBUFFER_COMPLETE) {
876 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
877 status, desc.fWidth, desc.fHeight);
878 continue;
879 }
880 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
881 #if GR_COLLECT_STATS
882 ++fStats.fRenderTargetChngCnt;
883 #endif
884 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
885 GR_COLOR_ATTACHMENT0,
886 GR_RENDERBUFFER,
887 rtIDs.fMSColorRenderbufferID));
888
889 }
890 if (rtIDs.fStencilRenderbufferID) {
891 // bind the stencil to rt fbo if present, othewise the tex fbo
892 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
893 GR_STENCIL_ATTACHMENT,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000894 GR_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000895 rtIDs.fStencilRenderbufferID));
896 }
897 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
898
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000899#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000900 // On some implementations you have to be bound as DEPTH_STENCIL.
901 // (Even binding to DEPTH and STENCIL separately with the same
902 // buffer doesn't work.)
903 if (rtIDs.fStencilRenderbufferID &&
904 status != GR_FRAMEBUFFER_COMPLETE) {
905 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
906 GR_STENCIL_ATTACHMENT,
907 GR_RENDERBUFFER,
908 0));
909 GR_GLEXT(fExts,
910 FramebufferRenderbuffer(GR_FRAMEBUFFER,
911 GR_DEPTH_STENCIL_ATTACHMENT,
912 GR_RENDERBUFFER,
913 rtIDs.fStencilRenderbufferID));
914 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
915 }
916#endif
917 if (status != GR_FRAMEBUFFER_COMPLETE) {
918 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
919 status, desc.fWidth, desc.fHeight);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000920#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000921 if (rtIDs.fStencilRenderbufferID) {
922 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
923 GR_DEPTH_STENCIL_ATTACHMENT,
924 GR_RENDERBUFFER,
925 0));
926 }
927#endif
928 continue;
929 }
930 // we're successful!
931 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000932 if (rtIDs.fStencilRenderbufferID) {
933 if (UNKNOWN_BITS == gStencilFormats[i].fBits) {
934 GR_GL_GetIntegerv(GL_STENCIL_BITS, (GLint*)&glDesc.fStencilBits);
935 } else {
936 glDesc.fStencilBits = gStencilFormats[i].fBits;
937 }
938 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000939 break;
940 }
941 if (failed) {
942 if (rtIDs.fStencilRenderbufferID) {
943 GR_GLEXT(fExts,
944 DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
945 }
946 if (rtIDs.fMSColorRenderbufferID) {
947 GR_GLEXT(fExts,
948 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
949 }
950 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
951 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
952 }
953 if (rtIDs.fTexFBOID) {
954 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
955 }
956 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
957 return return_null_texture();
958 }
959 }
960#ifdef TRACE_TEXTURE_CREATION
961 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
962 tex->fTextureID, width, height, tex->fUploadByteCount);
963#endif
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000964 GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, DEFAULT_PARAMS, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000965
966 if (0 != rtIDs.fTexFBOID) {
967 GrRenderTarget* rt = tex->asRenderTarget();
968 // We've messed with FBO state but may not have set the correct viewport
969 // so just dirty the rendertarget state to force a resend.
970 fHWDrawState.fRenderTarget = NULL;
971
972 // clear the new stencil buffer if we have one
973 if (!(desc.fFlags & kNoPathRendering_TextureFlag)) {
974 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
975 fCurrDrawState.fRenderTarget = rt;
976 eraseStencil(0, ~0);
977 fCurrDrawState.fRenderTarget = rtSave;
978 }
979 }
980 return tex;
981}
982
reed@google.comac10a2d2010-12-22 21:39:39 +0000983GrVertexBuffer* GrGpuGL::createVertexBuffer(uint32_t size, bool dynamic) {
984 GLuint id;
985 GR_GL(GenBuffers(1, &id));
986 if (id) {
987 GR_GL(BindBuffer(GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000988 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000989 GrGLClearErr();
990 // make sure driver can allocate memory for this buffer
991 GR_GL_NO_ERR(BufferData(GL_ARRAY_BUFFER, size, NULL,
992 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
993 if (glGetError() != GL_NO_ERROR) {
994 GR_GL(DeleteBuffers(1, &id));
995 // deleting bound buffer does implicit bind to 0
996 fHWGeometryState.fVertexBuffer = NULL;
997 return NULL;
998 }
999 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this,
1000 size, dynamic);
1001 fHWGeometryState.fVertexBuffer = vertexBuffer;
1002 return vertexBuffer;
1003 }
1004 return NULL;
1005}
1006
1007GrIndexBuffer* GrGpuGL::createIndexBuffer(uint32_t size, bool dynamic) {
1008 GLuint id;
1009 GR_GL(GenBuffers(1, &id));
1010 if (id) {
1011 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, id));
1012 GrGLClearErr();
1013 // make sure driver can allocate memory for this buffer
1014 GR_GL_NO_ERR(BufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1015 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
1016 if (glGetError() != GL_NO_ERROR) {
1017 GR_GL(DeleteBuffers(1, &id));
1018 // deleting bound buffer does implicit bind to 0
1019 fHWGeometryState.fIndexBuffer = NULL;
1020 return NULL;
1021 }
1022 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this,
1023 size, dynamic);
1024 fHWGeometryState.fIndexBuffer = indexBuffer;
1025 return indexBuffer;
1026 }
1027 return NULL;
1028}
1029
reed@google.comac10a2d2010-12-22 21:39:39 +00001030void GrGpuGL::flushScissor(const GrIRect* rect) {
1031 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001032 const GrGLIRect& vp =
reed@google.comac10a2d2010-12-22 21:39:39 +00001033 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1034
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001035 GrGLIRect scissor;
1036 if (NULL != rect) {
1037 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
1038 rect->width(), rect->height());
1039 if (scissor.contains(vp)) {
1040 rect = NULL;
1041 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001042 }
1043
1044 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001045 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001046 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001047 fHWBounds.fScissorRect = scissor;
1048 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001049 if (!fHWBounds.fScissorEnabled) {
1050 GR_GL(Enable(GL_SCISSOR_TEST));
1051 fHWBounds.fScissorEnabled = true;
1052 }
1053 } else {
1054 if (fHWBounds.fScissorEnabled) {
1055 GR_GL(Disable(GL_SCISSOR_TEST));
1056 fHWBounds.fScissorEnabled = false;
1057 }
1058 }
1059}
1060
reed@google.comac10a2d2010-12-22 21:39:39 +00001061void GrGpuGL::eraseColor(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001062 if (NULL == fCurrDrawState.fRenderTarget) {
1063 return;
1064 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001065 flushRenderTarget();
1066 if (fHWBounds.fScissorEnabled) {
1067 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001068 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001069 }
1070 GR_GL(ColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE));
1071 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1072 GrColorUnpackG(color)/255.f,
1073 GrColorUnpackB(color)/255.f,
1074 GrColorUnpackA(color)/255.f));
1075 GR_GL(Clear(GL_COLOR_BUFFER_BIT));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001076 fDirtyFlags.fWriteMaskChanged = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001077}
1078
1079void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001080 if (NULL == fCurrDrawState.fRenderTarget) {
1081 return;
1082 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001083 flushRenderTarget();
1084 if (fHWBounds.fScissorEnabled) {
1085 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001086 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001087 }
1088 GR_GL(StencilMask(mask));
1089 GR_GL(ClearStencil(value));
1090 GR_GL(Clear(GL_STENCIL_BUFFER_BIT));
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001091 fDirtyFlags.fWriteMaskChanged = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001092}
1093
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001094void GrGpuGL::eraseStencilClip() {
1095 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1096 GLint stencilBitCount = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getStencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 GrAssert(stencilBitCount > 0);
1098 GLint clipStencilMask = (1 << (stencilBitCount - 1));
1099 eraseStencil(0, clipStencilMask);
1100}
1101
1102void GrGpuGL::forceRenderTargetFlush() {
1103 flushRenderTarget();
1104}
1105
1106bool GrGpuGL::readPixels(int left, int top, int width, int height,
1107 GrTexture::PixelConfig config, void* buffer) {
1108 GLenum internalFormat; // we don't use this for glReadPixels
1109 GLenum format;
1110 GLenum type;
1111 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1112 return false;
1113 }
1114
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001115 if (NULL == fCurrDrawState.fRenderTarget) {
1116 return false;
1117 }
1118 flushRenderTarget();
1119
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001120 const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1121
1122 // the read rect is viewport-relative
1123 GrGLIRect readRect;
1124 readRect.setRelativeTo(glvp, left, top, width, height);
1125 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
1126 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001127 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001128
1129 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1130 // API presents top-to-bottom
1131 {
1132 size_t stride = width * GrTexture::BytesPerPixel(config);
1133 GrAutoMalloc rowStorage(stride);
1134 void* tmp = rowStorage.get();
1135
1136 const int halfY = height >> 1;
1137 char* top = reinterpret_cast<char*>(buffer);
1138 char* bottom = top + (height - 1) * stride;
1139 for (int y = 0; y < halfY; y++) {
1140 memcpy(tmp, top, stride);
1141 memcpy(top, bottom, stride);
1142 memcpy(bottom, tmp, stride);
1143 top += stride;
1144 bottom -= stride;
1145 }
1146 }
1147 return true;
1148}
1149
1150void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001151
1152 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1153
reed@google.comac10a2d2010-12-22 21:39:39 +00001154 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1155 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
1156 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
1157 #if GR_COLLECT_STATS
1158 ++fStats.fRenderTargetChngCnt;
1159 #endif
1160 rt->setDirty(true);
1161 #if GR_DEBUG
1162 GLenum status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
1163 if (status != GR_FRAMEBUFFER_COMPLETE) {
1164 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1165 }
1166 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001167 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001168 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
1169 const GrGLIRect& vp = rt->viewport();
1170 if (true || fHWBounds.fViewportRect != vp) {
1171 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001172 fHWBounds.fViewportRect = vp;
1173 }
1174 }
1175}
1176
1177GLenum gPrimitiveType2GLMode[] = {
1178 GL_TRIANGLES,
1179 GL_TRIANGLE_STRIP,
1180 GL_TRIANGLE_FAN,
1181 GL_POINTS,
1182 GL_LINES,
1183 GL_LINE_STRIP
1184};
1185
bsalomon@google.comffca4002011-02-22 20:34:01 +00001186void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001187 uint32_t startVertex,
1188 uint32_t startIndex,
1189 uint32_t vertexCount,
1190 uint32_t indexCount) {
1191 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1192
1193 GLvoid* indices = (GLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001194
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001195 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1196 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1197
1198 // our setupGeometry better have adjusted this to zero since
1199 // DrawElements always draws from the begining of the arrays for idx 0.
1200 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001201
1202 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1203 GL_UNSIGNED_SHORT, indices));
1204}
1205
bsalomon@google.comffca4002011-02-22 20:34:01 +00001206void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001207 uint32_t startVertex,
1208 uint32_t vertexCount) {
1209 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1210
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001211 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1212
1213 // our setupGeometry better have adjusted this to zero.
1214 // DrawElements doesn't take an offset so we always adjus the startVertex.
1215 GrAssert(0 == startVertex);
1216
1217 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1218 // account for startVertex in the DrawElements case. So we always
1219 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001220 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1221}
1222
reed@google.comac10a2d2010-12-22 21:39:39 +00001223void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1224 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1225
1226 if (NULL != rt && rt->needsResolve()) {
1227 GrAssert(kNone_MSFBO != fMSFBOType);
1228 GrAssert(rt->textureFBOID() != rt->renderFBOID());
1229 GR_GLEXT(fExts, BindFramebuffer(GR_READ_FRAMEBUFFER,
1230 rt->renderFBOID()));
1231 GR_GLEXT(fExts, BindFramebuffer(GR_DRAW_FRAMEBUFFER,
1232 rt->textureFBOID()));
1233 #if GR_COLLECT_STATS
1234 ++fStats.fRenderTargetChngCnt;
1235 #endif
1236 // make sure we go through set render target
1237 fHWDrawState.fRenderTarget = NULL;
1238
1239 GLint left = 0;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001240 GLint right = texture->width();
reed@google.comac10a2d2010-12-22 21:39:39 +00001241 // we will have rendered to the top of the FBO.
1242 GLint top = texture->allocHeight();
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001243 GLint bottom = texture->allocHeight() - texture->height();
reed@google.comac10a2d2010-12-22 21:39:39 +00001244 if (kApple_MSFBO == fMSFBOType) {
1245 GR_GL(Enable(GL_SCISSOR_TEST));
1246 GR_GL(Scissor(left, bottom, right-left, top-bottom));
1247 GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001248 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001249 fHWBounds.fScissorEnabled = true;
1250 } else {
1251 GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
1252 left, bottom, right, top,
1253 GL_COLOR_BUFFER_BIT, GL_NEAREST));
1254 }
1255 rt->setDirty(false);
1256
1257 }
1258}
1259
1260void GrGpuGL::flushStencil() {
1261
1262 // use stencil for clipping if clipping is enabled and the clip
1263 // has been written into the stencil.
1264 bool stencilClip = fClipState.fClipInStencil &&
1265 (kClip_StateBit & fCurrDrawState.fFlagBits);
1266 bool stencilChange =
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001267 fDirtyFlags.fWriteMaskChanged ||
reed@google.comac10a2d2010-12-22 21:39:39 +00001268 fHWStencilClip != stencilClip ||
1269 fHWDrawState.fStencilPass != fCurrDrawState.fStencilPass ||
1270 (kNone_StencilPass != fCurrDrawState.fStencilPass &&
1271 (StencilPass)kSetClip_StencilPass != fCurrDrawState.fStencilPass &&
1272 fHWDrawState.fReverseFill != fCurrDrawState.fReverseFill);
1273
1274 if (stencilChange) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001275 GLint clipStencilMask;
1276 GLint pathStencilMask;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001277 GLint stencilBitCount = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getStencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001278 GrAssert(stencilBitCount > 0 ||
1279 kNone_StencilPass == fCurrDrawState.fStencilPass);
1280 clipStencilMask = (1 << (stencilBitCount - 1));
1281 pathStencilMask = clipStencilMask - 1;
1282 switch (fCurrDrawState.fStencilPass) {
1283 case kNone_StencilPass:
1284 if (stencilClip) {
1285 GR_GL(Enable(GL_STENCIL_TEST));
1286 GR_GL(StencilFunc(GL_EQUAL,
1287 clipStencilMask,
1288 clipStencilMask));
1289 GR_GL(StencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
1290 } else {
1291 GR_GL(Disable(GL_STENCIL_TEST));
1292 }
1293 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1294 if (!fSingleStencilPassForWinding) {
1295 GR_GL(Disable(GL_CULL_FACE));
1296 }
1297 break;
1298 case kEvenOddStencil_StencilPass:
1299 GR_GL(Enable(GL_STENCIL_TEST));
1300 if (stencilClip) {
1301 GR_GL(StencilFunc(GL_EQUAL, clipStencilMask, clipStencilMask));
1302 } else {
1303 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1304 }
1305 GR_GL(StencilMask(pathStencilMask));
1306 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1307 GR_GL(StencilOp(GL_KEEP, GL_INVERT, GL_INVERT));
1308 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1309 if (!fSingleStencilPassForWinding) {
1310 GR_GL(Disable(GL_CULL_FACE));
1311 }
1312 break;
1313 case kEvenOddColor_StencilPass: {
1314 GR_GL(Enable(GL_STENCIL_TEST));
1315 GLint funcRef = 0;
1316 GLuint funcMask = pathStencilMask;
1317 if (stencilClip) {
1318 funcRef |= clipStencilMask;
1319 funcMask |= clipStencilMask;
1320 }
1321 if (!fCurrDrawState.fReverseFill) {
1322 funcRef |= pathStencilMask;
1323 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001324
bsalomon@google.com316f99232011-01-13 21:28:12 +00001325 GR_GL(StencilFunc(GL_EQUAL, funcRef, funcMask));
1326 GR_GL(StencilMask(pathStencilMask));
reed@google.comac10a2d2010-12-22 21:39:39 +00001327 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1328 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1329 if (!fSingleStencilPassForWinding) {
1330 GR_GL(Disable(GL_CULL_FACE));
1331 }
1332 } break;
1333 case kWindingStencil1_StencilPass:
1334 GR_GL(Enable(GL_STENCIL_TEST));
1335 if (fHasStencilWrap) {
1336 if (stencilClip) {
1337 GR_GL(StencilFunc(GL_EQUAL,
1338 clipStencilMask,
1339 clipStencilMask));
1340 } else {
1341 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1342 }
1343 if (fSingleStencilPassForWinding) {
1344 GR_GL(StencilOpSeparate(GL_FRONT, GL_KEEP,
1345 GL_INCR_WRAP, GL_INCR_WRAP));
1346 GR_GL(StencilOpSeparate(GL_BACK, GL_KEEP,
1347 GL_DECR_WRAP, GL_DECR_WRAP));
1348 } else {
1349 GR_GL(StencilOp(GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP));
1350 GR_GL(Enable(GL_CULL_FACE));
1351 GR_GL(CullFace(GL_BACK));
1352 }
1353 } else {
1354 // If we don't have wrap then we use the Func to detect
1355 // values that would wrap (0 on decr and mask on incr). We
1356 // make the func fail on these values and use the sfail op
1357 // to effectively wrap by inverting.
1358 // This applies whether we are doing a two-pass (front faces
1359 // followed by back faces) or a single pass (separate func/op)
1360
1361 // Note that in the case where we are also using stencil to
1362 // clip this means we will write into the path bits in clipped
1363 // out pixels. We still apply the clip bit in the color pass
1364 // stencil func so we don't draw color outside the clip.
1365 // We also will clear the stencil bits in clipped pixels by
1366 // using zero in the sfail op with write mask set to the
1367 // path mask.
1368 GR_GL(Enable(GL_STENCIL_TEST));
1369 if (fSingleStencilPassForWinding) {
1370 GR_GL(StencilFuncSeparate(GL_FRONT,
1371 GL_NOTEQUAL,
1372 pathStencilMask,
1373 pathStencilMask));
1374 GR_GL(StencilFuncSeparate(GL_BACK,
1375 GL_NOTEQUAL,
1376 0x0,
1377 pathStencilMask));
1378 GR_GL(StencilOpSeparate(GL_FRONT, GL_INVERT,
1379 GL_INCR, GL_INCR));
1380 GR_GL(StencilOpSeparate(GL_BACK, GL_INVERT,
1381 GL_DECR, GL_DECR));
1382 } else {
1383 GR_GL(StencilFunc(GL_NOTEQUAL,
1384 pathStencilMask,
1385 pathStencilMask));
1386 GR_GL(StencilOp(GL_INVERT, GL_INCR, GL_INCR));
1387 GR_GL(Enable(GL_CULL_FACE));
1388 GR_GL(CullFace(GL_BACK));
1389 }
1390 }
1391 GR_GL(StencilMask(pathStencilMask));
1392 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1393 break;
1394 case kWindingStencil2_StencilPass:
1395 GrAssert(!fSingleStencilPassForWinding);
1396 GR_GL(Enable(GL_STENCIL_TEST));
1397 if (fHasStencilWrap) {
1398 if (stencilClip) {
1399 GR_GL(StencilFunc(GL_EQUAL,
1400 clipStencilMask,
1401 clipStencilMask));
1402 } else {
1403 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1404 }
1405 GR_GL(StencilOp(GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP));
1406 } else {
1407 GR_GL(StencilFunc(GL_NOTEQUAL, 0x0, pathStencilMask));
1408 GR_GL(StencilOp(GL_INVERT, GL_DECR, GL_DECR));
1409 }
1410 GR_GL(StencilMask(pathStencilMask));
1411 GR_GL(Enable(GL_CULL_FACE));
1412 GR_GL(CullFace(GL_FRONT));
1413 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1414 break;
1415 case kWindingColor_StencilPass: {
1416 GR_GL(Enable(GL_STENCIL_TEST));
1417 GLint funcRef = 0;
1418 GLuint funcMask = pathStencilMask;
1419 GLenum funcFunc;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001420
reed@google.comac10a2d2010-12-22 21:39:39 +00001421 if (stencilClip) {
1422 funcRef |= clipStencilMask;
1423 funcMask |= clipStencilMask;
1424 }
1425 if (fCurrDrawState.fReverseFill) {
1426 funcFunc = GL_EQUAL;
1427 } else {
1428 funcFunc = GL_LESS;
1429 }
1430 GR_GL(StencilFunc(funcFunc, funcRef, funcMask));
1431 GR_GL(StencilMask(pathStencilMask));
1432 // must zero in sfail because winding w/o wrap will write
1433 // path stencil bits in clipped out pixels
1434 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1435 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1436 if (!fSingleStencilPassForWinding) {
1437 GR_GL(Disable(GL_CULL_FACE));
1438 }
1439 } break;
1440 case kSetClip_StencilPass:
1441 GR_GL(Enable(GL_STENCIL_TEST));
1442 GR_GL(StencilFunc(GL_ALWAYS, clipStencilMask, clipStencilMask));
1443 GR_GL(StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
1444 GR_GL(StencilMask(clipStencilMask));
1445 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1446 if (!fSingleStencilPassForWinding) {
1447 GR_GL(Disable(GL_CULL_FACE));
1448 }
1449 break;
1450 default:
1451 GrAssert(!"Unexpected stencil pass.");
1452 break;
1453
1454 }
1455 fHWDrawState.fStencilPass = fCurrDrawState.fStencilPass;
1456 fHWDrawState.fReverseFill = fCurrDrawState.fReverseFill;
reed@google.comac10a2d2010-12-22 21:39:39 +00001457 fHWStencilClip = stencilClip;
1458 }
1459}
1460
bsalomon@google.comffca4002011-02-22 20:34:01 +00001461bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001462
1463 // GrGpu::setupClipAndFlushState should have already checked this
1464 // and bailed if not true.
1465 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001466
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001467 for (int s = 0; s < kNumStages; ++s) {
1468 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001469
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001470 // bind texture and set sampler state
1471 if (usingTexture) {
1472 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001473
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001474 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001475 // if we created a rt/tex and rendered to it without using a
1476 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001477 // the last bound texture, but it needs resolving. So keep this
1478 // out of the "last != next" check.
1479 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001480
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001481 if (fHWDrawState.fTextures[s] != nextTexture) {
1482 setTextureUnit(s);
1483 GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
1484 #if GR_COLLECT_STATS
1485 ++fStats.fTextureChngCnt;
1486 #endif
1487 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1488 fHWDrawState.fTextures[s] = nextTexture;
1489 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001490
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001491 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001492 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001493 nextTexture->getTexParams();
1494 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001495
1496 newTexParams.fFilter = sampler.isFilter() ? GL_LINEAR :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001497 GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001498 newTexParams.fWrapS =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001499 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001500 newTexParams.fWrapT =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001501 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001502
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001503 if (newTexParams.fFilter != oldTexParams.fFilter) {
1504 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001505 GR_GL(TexParameteri(GL_TEXTURE_2D,
1506 GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001507 newTexParams.fFilter));
bsalomon@google.com316f99232011-01-13 21:28:12 +00001508 GR_GL(TexParameteri(GL_TEXTURE_2D,
1509 GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001510 newTexParams.fFilter));
1511 }
1512 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1513 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001514 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001515 GL_TEXTURE_WRAP_S,
1516 newTexParams.fWrapS));
1517 }
1518 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1519 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001520 GR_GL(TexParameteri(GL_TEXTURE_2D,
1521 GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001522 newTexParams.fWrapT));
1523 }
1524 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001525
1526 // The texture matrix has to compensate for texture width/height
1527 // and NPOT-embedded-in-POT
1528 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001529 } else {
1530 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001531 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001532 }
1533 }
1534 }
1535
1536 flushRenderTarget();
1537
1538 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1539 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1540 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
1541 GR_GL(Enable(GL_DITHER));
1542 } else {
1543 GR_GL(Disable(GL_DITHER));
1544 }
1545 }
1546
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001547#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +00001548 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1549 // smooth lines.
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001550 if (fDirtyFlags.fRenderTargetChanged ||
reed@google.comac10a2d2010-12-22 21:39:39 +00001551 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1552 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1553 GLint msaa = 0;
1554 // only perform query if we know MSAA is supported.
1555 // calling on non-MSAA target caused a crash in one environment,
1556 // though I don't think it should.
reed@google.coma09368c2011-02-24 21:42:29 +00001557 if (fAASamples[kHigh_AALevel]) {
reed@google.comac20fb92011-01-12 17:14:53 +00001558 GR_GL_GetIntegerv(GL_SAMPLE_BUFFERS, &msaa);
reed@google.comac10a2d2010-12-22 21:39:39 +00001559 }
1560 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1561 if (msaa) {
1562 GR_GL(Enable(GL_MULTISAMPLE));
1563 } else {
1564 GR_GL(Enable(GL_LINE_SMOOTH));
1565 }
1566 } else {
1567 if (msaa) {
1568 GR_GL(Disable(GL_MULTISAMPLE));
1569 }
1570 GR_GL(Disable(GL_LINE_SMOOTH));
1571 }
1572 }
1573#endif
1574
1575 bool blendOff = canDisableBlend();
1576 if (fHWBlendDisabled != blendOff) {
1577 if (blendOff) {
1578 GR_GL(Disable(GL_BLEND));
1579 } else {
1580 GR_GL(Enable(GL_BLEND));
1581 }
1582 fHWBlendDisabled = blendOff;
1583 }
1584
1585 if (!blendOff) {
1586 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1587 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1588 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1589 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1590 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1591 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1592 }
1593 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001594
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001595#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001596 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001597 for (int s = 0; s < kNumStages; ++s) {
1598 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1599 NULL == fCurrDrawState.fRenderTarget ||
1600 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001601 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001602 fCurrDrawState.fRenderTarget);
1603 }
1604#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001605
reed@google.comac10a2d2010-12-22 21:39:39 +00001606 flushStencil();
1607
1608 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001609 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001610}
1611
1612void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001613 if (fHWGeometryState.fVertexBuffer != buffer) {
1614 fHWGeometryState.fArrayPtrsDirty = true;
1615 fHWGeometryState.fVertexBuffer = buffer;
1616 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001617}
1618
1619void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1620 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1621 buffer == fGeometrySrc.fVertexBuffer));
1622
1623 if (fHWGeometryState.fVertexBuffer == buffer) {
1624 // deleting bound buffer does implied bind to 0
1625 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001626 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001627 }
1628}
1629
1630void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1631 fGeometrySrc.fIndexBuffer = buffer;
1632}
1633
1634void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1635 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1636 buffer == fGeometrySrc.fIndexBuffer));
1637
1638 if (fHWGeometryState.fIndexBuffer == buffer) {
1639 // deleting bound buffer does implied bind to 0
1640 fHWGeometryState.fIndexBuffer = NULL;
1641 }
1642}
1643
reed@google.comac10a2d2010-12-22 21:39:39 +00001644void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1645 GrAssert(NULL != renderTarget);
1646
1647 // if the bound FBO is destroyed we can't rely on the implicit bind to 0
1648 // a) we want the default RT which may not be FBO 0
1649 // b) we set more state than just FBO based on the RT
1650 // So trash the HW state to force an RT flush next time
1651 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001652 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001653 }
1654 if (fHWDrawState.fRenderTarget == renderTarget) {
1655 fHWDrawState.fRenderTarget = NULL;
1656 }
1657 if (fClipState.fStencilClipTarget == renderTarget) {
1658 fClipState.fStencilClipTarget = NULL;
1659 }
1660}
1661
1662void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001663 for (int s = 0; s < kNumStages; ++s) {
1664 if (fCurrDrawState.fTextures[s] == texture) {
1665 fCurrDrawState.fTextures[s] = NULL;
1666 }
1667 if (fHWDrawState.fTextures[s] == texture) {
1668 // deleting bound texture does implied bind to 0
1669 fHWDrawState.fTextures[s] = NULL;
1670 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001671 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001672}
1673
1674void GrGpuGL::notifyTextureRemoveRenderTarget(GrGLTexture* texture) {
1675 GrAssert(NULL != texture->asRenderTarget());
1676
1677 // if there is a pending resolve, perform it.
1678 resolveTextureRenderTarget(texture);
1679}
1680
1681bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
1682 GLenum* internalFormat,
1683 GLenum* format,
1684 GLenum* type) {
1685 switch (config) {
1686 case GrTexture::kRGBA_8888_PixelConfig:
1687 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001688 *format = GR_GL_32BPP_COLOR_FORMAT;
reed@google.com63100f92011-01-18 21:32:14 +00001689#if GR_SUPPORT_GLES
1690 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1691 // format for a BGRA is BGRA not RGBA (as on desktop)
1692 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1693#else
1694 *internalFormat = GL_RGBA;
bsalomon@google.comed3a0682011-01-18 16:54:04 +00001695#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001696 *type = GL_UNSIGNED_BYTE;
1697 break;
1698 case GrTexture::kRGB_565_PixelConfig:
1699 *format = GL_RGB;
1700 *internalFormat = GL_RGB;
1701 *type = GL_UNSIGNED_SHORT_5_6_5;
1702 break;
1703 case GrTexture::kRGBA_4444_PixelConfig:
1704 *format = GL_RGBA;
1705 *internalFormat = GL_RGBA;
1706 *type = GL_UNSIGNED_SHORT_4_4_4_4;
1707 break;
1708 case GrTexture::kIndex_8_PixelConfig:
1709 if (this->supports8BitPalette()) {
1710 *format = GR_PALETTE8_RGBA8;
1711 *internalFormat = GR_PALETTE8_RGBA8;
1712 *type = GL_UNSIGNED_BYTE; // unused I think
1713 } else {
1714 return false;
1715 }
1716 break;
1717 case GrTexture::kAlpha_8_PixelConfig:
1718 *format = GL_ALPHA;
1719 *internalFormat = GL_ALPHA;
1720 *type = GL_UNSIGNED_BYTE;
1721 break;
1722 default:
1723 return false;
1724 }
1725 return true;
1726}
1727
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001728void GrGpuGL::setTextureUnit(int unit) {
1729 GrAssert(unit >= 0 && unit < kNumStages);
1730 if (fActiveTextureUnitIdx != unit) {
1731 GR_GL(ActiveTexture(GL_TEXTURE0 + unit));
1732 fActiveTextureUnitIdx = unit;
1733 }
1734}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001735
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001736void GrGpuGL::setSpareTextureUnit() {
1737 if (fActiveTextureUnitIdx != (GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1738 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
1739 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1740 }
1741}
1742
reed@google.comac10a2d2010-12-22 21:39:39 +00001743/* On ES the internalFormat and format must match for TexImage and we use
1744 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1745 decide the internalFormat. However, on ES internalFormat for
1746 RenderBufferStorage* has to be a specific format (not a base format like
1747 GL_RGBA).
1748 */
1749bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) {
1750 switch (config) {
1751 case GrTexture::kRGBA_8888_PixelConfig:
1752 case GrTexture::kRGBX_8888_PixelConfig:
1753 if (fRGBA8Renderbuffer) {
1754 *format = GR_RGBA8;
1755 return true;
1756 } else {
1757 return false;
1758 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001759#if GR_SUPPORT_GLES // ES2 supports 565. ES1 supports it with FBO extension
1760 // desktop GL has no such internal format
reed@google.comac10a2d2010-12-22 21:39:39 +00001761 case GrTexture::kRGB_565_PixelConfig:
1762 *format = GR_RGB565;
1763 return true;
1764#endif
1765 case GrTexture::kRGBA_4444_PixelConfig:
1766 *format = GL_RGBA4;
1767 return true;
1768 default:
1769 return false;
1770 }
1771}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001772
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001773void GrGpuGL::resetDirtyFlags() {
1774 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1775}
1776
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001777void GrGpuGL::setBuffers(bool indexed,
1778 int* extraVertexOffset,
1779 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001780
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001781 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001782
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001783 GrGLVertexBuffer* vbuf;
1784 switch (fGeometrySrc.fVertexSrc) {
1785 case kBuffer_GeometrySrcType:
1786 *extraVertexOffset = 0;
1787 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1788 break;
1789 case kArray_GeometrySrcType:
1790 case kReserved_GeometrySrcType:
1791 finalizeReservedVertices();
1792 *extraVertexOffset = fCurrPoolStartVertex;
1793 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1794 break;
1795 default:
1796 vbuf = NULL; // suppress warning
1797 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001798 }
1799
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001800 GrAssert(NULL != vbuf);
1801 GrAssert(!vbuf->isLocked());
1802 if (fHWGeometryState.fVertexBuffer != vbuf) {
1803 GR_GL(BindBuffer(GL_ARRAY_BUFFER, vbuf->bufferID()));
1804 fHWGeometryState.fArrayPtrsDirty = true;
1805 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001806 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001807
1808 if (indexed) {
1809 GrAssert(NULL != extraIndexOffset);
1810
1811 GrGLIndexBuffer* ibuf;
1812 switch (fGeometrySrc.fIndexSrc) {
1813 case kBuffer_GeometrySrcType:
1814 *extraIndexOffset = 0;
1815 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1816 break;
1817 case kArray_GeometrySrcType:
1818 case kReserved_GeometrySrcType:
1819 finalizeReservedIndices();
1820 *extraIndexOffset = fCurrPoolStartIndex;
1821 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1822 break;
1823 default:
1824 ibuf = NULL; // suppress warning
1825 GrCrash("Unknown geometry src type!");
1826 }
1827
1828 GrAssert(NULL != ibuf);
1829 GrAssert(!ibuf->isLocked());
1830 if (fHWGeometryState.fIndexBuffer != ibuf) {
1831 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
1832 fHWGeometryState.fIndexBuffer = ibuf;
1833 }
1834 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001835}