blob: 7a83ac8b267b7bbb5e944c15615206acb3191921 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#include "GrGpuGL.h"
18#include "GrMemory.h"
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +000019#if GR_WIN32_BUILD
20 // need to get wglGetProcAddress
21 #undef WIN32_LEAN_AND_MEAN
22 #define WIN32_LEAN_AND_MEAN 1
23 #include <windows.h>
24 #undef WIN32_LEAN_AND_MEAN
25#endif
26
reed@google.comac10a2d2010-12-22 21:39:39 +000027
28static const GLuint GR_MAX_GLUINT = ~0;
29static const GLint GR_INVAL_GLINT = ~0;
30
bsalomon@google.com316f99232011-01-13 21:28:12 +000031// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000032// mucking with the state of any of the stages.
bsalomon@google.com316f99232011-01-13 21:28:12 +000033static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000034
reed@google.comac10a2d2010-12-22 21:39:39 +000035#define SKIP_CACHE_CHECK true
36
37static const GLenum gXfermodeCoeff2Blend[] = {
38 GL_ZERO,
39 GL_ONE,
40 GL_SRC_COLOR,
41 GL_ONE_MINUS_SRC_COLOR,
42 GL_DST_COLOR,
43 GL_ONE_MINUS_DST_COLOR,
44 GL_SRC_ALPHA,
45 GL_ONE_MINUS_SRC_ALPHA,
46 GL_DST_ALPHA,
47 GL_ONE_MINUS_DST_ALPHA,
48};
49
reed@google.comac10a2d2010-12-22 21:39:39 +000050///////////////////////////////////////////////////////////////////////////////
51
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +000052static bool gPrintStartupSpew;
53
54
reed@google.comac10a2d2010-12-22 21:39:39 +000055bool fbo_test(GrGLExts exts, int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000056
57 GLint savedFBO;
58 GLint savedTexUnit;
reed@google.com3d8de042011-01-20 02:18:00 +000059 GR_GL_GetIntegerv(GL_ACTIVE_TEXTURE, &savedTexUnit);
60 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +000061
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000062 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +000063
reed@google.comac10a2d2010-12-22 21:39:39 +000064 GLuint testFBO;
65 GR_GLEXT(exts, GenFramebuffers(1, &testFBO));
66 GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, testFBO));
67 GLuint testRTTex;
68 GR_GL(GenTextures(1, &testRTTex));
69 GR_GL(BindTexture(GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +000070 // some implementations require texture to be mip-map complete before
71 // FBO with level 0 bound as color attachment will be framebuffer complete.
72 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +000073 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h,
74 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
75 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
76 GR_GLEXT(exts, FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0,
77 GL_TEXTURE_2D, testRTTex, 0));
78 GLenum status = GR_GLEXT(exts, CheckFramebufferStatus(GR_FRAMEBUFFER));
79 GR_GLEXT(exts, DeleteFramebuffers(1, &testFBO));
80 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +000081
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000082 GR_GL(ActiveTexture(savedTexUnit));
83 GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +000084
reed@google.comac10a2d2010-12-22 21:39:39 +000085 return status == GR_FRAMEBUFFER_COMPLETE;
86}
87
reed@google.comac10a2d2010-12-22 21:39:39 +000088GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +000089
90#if GR_GL_NO_CLIENT_SIDE_ARRAYS
91 fClientArrayVB = NULL;
92 fClientArrayIB = NULL;
93 fOversizeVBDrawCnt = 0;
94 fOversizeIBDrawCnt = 0;
95#endif
96
reed@google.comeeeb5a02010-12-23 15:12:59 +000097 if (gPrintStartupSpew) {
98 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
99 this);
100 GrPrintf("------ VENDOR %s\n", glGetString(GL_VENDOR));
101 GrPrintf("------ RENDERER %s\n", glGetString(GL_RENDERER));
102 GrPrintf("------ VERSION %s\n", glGetString(GL_VERSION));
103 GrPrintf("------ EXTENSIONS\n %s \n", glGetString(GL_EXTENSIONS));
104 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000105
106 GrGLClearErr();
107
108 GrGLInitExtensions(&fExts);
109
110 resetContextHelper();
111
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000112 fHWDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000113 fRenderTargetChanged = true;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000114
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000115 GLint maxTextureUnits;
116 // check FS and fixed-function texture unit limits
117 // we only use textures in the fragment stage currently.
118 // checks are > to make sure we have a spare unit.
119#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES2
reed@google.com3d8de042011-01-20 02:18:00 +0000120 GR_GL_GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000121 GrAssert(maxTextureUnits > kNumStages);
122#endif
123#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1
reed@google.com3d8de042011-01-20 02:18:00 +0000124 GR_GL_GetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000125 GrAssert(maxTextureUnits > kNumStages);
126#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +0000127
reed@google.comac10a2d2010-12-22 21:39:39 +0000128 fCurrDrawState = fHWDrawState;
129
130 ////////////////////////////////////////////////////////////////////////////
131 // Check for supported features.
132
133 int major, minor;
134 gl_version(&major, &minor);
135
136 GLint numFormats;
reed@google.comac20fb92011-01-12 17:14:53 +0000137 GR_GL_GetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000138 GrAutoSTMalloc<10, GLint> formats(numFormats);
reed@google.comac20fb92011-01-12 17:14:53 +0000139 GR_GL_GetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000140 for (int i = 0; i < numFormats; ++i) {
141 if (formats[i] == GR_PALETTE8_RGBA8) {
142 f8bitPaletteSupport = true;
143 break;
144 }
145 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000146
147 if (gPrintStartupSpew) {
148 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
149 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000150
151 GR_STATIC_ASSERT(0 == kNone_AALevel);
152 GR_STATIC_ASSERT(1 == kLow_AALevel);
153 GR_STATIC_ASSERT(2 == kMed_AALevel);
154 GR_STATIC_ASSERT(3 == kHigh_AALevel);
155
156 memset(fAASamples, 0, sizeof(fAASamples));
157 fMSFBOType = kNone_MSFBO;
158 if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
159 fMSFBOType = kIMG_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000160 if (gPrintStartupSpew) {
161 GrPrintf("MSAA Support: IMG ES EXT.\n");
162 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000163 }
164 else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
165 fMSFBOType = kApple_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000166 if (gPrintStartupSpew) {
167 GrPrintf("MSAA Support: APPLE ES EXT.\n");
168 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000169 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000170#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000171 else if ((major >= 3) ||
172 has_gl_extension("GL_ARB_framebuffer_object") ||
173 (has_gl_extension("GL_EXT_framebuffer_multisample") &&
174 has_gl_extension("GL_EXT_framebuffer_blit"))) {
175 fMSFBOType = kDesktop_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000176 if (gPrintStartupSpew) {
177 GrPrintf("MSAA Support: DESKTOP\n");
178 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000179 }
180#endif
181 else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000182 if (gPrintStartupSpew) {
183 GrPrintf("MSAA Support: NONE\n");
184 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000185 }
186
187 if (kNone_MSFBO != fMSFBOType) {
188 GLint maxSamples;
189 GLenum maxSampleGetter = (kIMG_MSFBO == fMSFBOType) ?
190 GR_MAX_SAMPLES_IMG :
191 GR_MAX_SAMPLES;
reed@google.comac20fb92011-01-12 17:14:53 +0000192 GR_GL_GetIntegerv(maxSampleGetter, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000193 if (maxSamples > 1 ) {
194 fAASamples[kNone_AALevel] = 0;
195 fAASamples[kLow_AALevel] = GrMax(2,
196 GrFixedFloorToInt((GR_FixedHalf) *
197 maxSamples));
198 fAASamples[kMed_AALevel] = GrMax(2,
199 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
200 maxSamples));
201 fAASamples[kHigh_AALevel] = maxSamples;
202 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000203 if (gPrintStartupSpew) {
204 GrPrintf("\tMax Samples: %d\n", maxSamples);
205 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000206 }
207
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000208#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000209 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
210 has_gl_extension("GL_EXT_stencil_wrap");
211#else
212 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
213#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000214 if (gPrintStartupSpew) {
215 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
216 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000217
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000218#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000219 // we could also look for GL_ATI_separate_stencil extension or
220 // GL_EXT_stencil_two_side but they use different function signatures
221 // than GL2.0+ (and than each other).
222 fSingleStencilPassForWinding = (major >= 2);
223#else
224 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
225 // an ES1 extension.
226 fSingleStencilPassForWinding = (major >= 2);
227#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000228 if (gPrintStartupSpew) {
229 GrPrintf("Single Stencil Pass For Winding: %s\n", (fSingleStencilPassForWinding ? "YES" : "NO"));
230 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000231
232
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000233#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000234 fRGBA8Renderbuffer = true;
235#else
236 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
237#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000238 if (gPrintStartupSpew) {
239 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
240 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000241
bsalomon@google.comed3a0682011-01-18 16:54:04 +0000242#if GR_SUPPORT_GLES
243 if (GR_GL_32BPP_COLOR_FORMAT == GR_BGRA) {
244 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
245 }
246#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000247
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000248#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000249 fBufferLockSupport = true; // we require VBO support and the desktop VBO
250 // extension includes glMapBuffer.
251#else
252 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
253#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000254 if (gPrintStartupSpew) {
255 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
256 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000257
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000258#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com0748f212011-02-01 22:56:16 +0000259 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
260 fNPOTTextureTileSupport = true;
261 fNPOTTextureSupport = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000262 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000263 fNPOTTextureTileSupport = false;
264 fNPOTTextureSupport = false;
265 }
266#else
267 if (major >= 2) {
268 fNPOTTextureSupport = true;
269 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
270 } else {
271 fNPOTTextureSupport = has_gl_extension("GL_APPLE_texture_2D_limited_npot");
272 fNPOTTextureTileSupport = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000273 }
274#endif
275 ////////////////////////////////////////////////////////////////////////////
276 // Experiments to determine limitations that can't be queried. TODO: Make
277 // these a preprocess that generate some compile time constants.
278
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000279 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000280
bsalomon@google.com0748f212011-02-01 22:56:16 +0000281 bool simpleFBOSuccess = fbo_test(fExts, 128, 128);
282 if (gPrintStartupSpew) {
283 if (!simpleFBOSuccess) {
284 GrPrintf("FBO Sanity Test: FAILED\n");
285 } else {
286 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000287 }
288 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000289 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000290
reed@google.comac10a2d2010-12-22 21:39:39 +0000291 /* Experimentation has found that some GLs that support NPOT textures
292 do not support FBOs with a NPOT texture. They report "unsupported" FBO
293 status. I don't know how to explicitly query for this. Do an
294 experiment. Note they may support NPOT with a renderbuffer but not a
295 texture. Presumably, the implementation bloats the renderbuffer
296 internally to the next POT.
297 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000298 bool fNPOTRenderTargetSupport = false;
299 if (fNPOTTextureSupport) {
300 fNPOTRenderTargetSupport = fbo_test(fExts, 200, 200);
301 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000302
bsalomon@google.com0748f212011-02-01 22:56:16 +0000303 if (gPrintStartupSpew) {
304 if (fNPOTTextureSupport) {
305 GrPrintf("NPOT textures supported\n");
306 if (fNPOTTextureTileSupport) {
307 GrPrintf("NPOT texture tiling supported\n");
308 } else {
309 GrPrintf("NPOT texture tiling NOT supported\n");
310 }
311 if (fNPOTRenderTargetSupport) {
312 GrPrintf("NPOT render targets supported\n");
313 } else {
314 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000315 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000316 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000317 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000318 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000319 }
320
reed@google.comac10a2d2010-12-22 21:39:39 +0000321 /* The iPhone 4 has a restriction that for an FBO with texture color
322 attachment with height <= 8 then the width must be <= height. Here
323 we look for such a limitation.
324 */
325 fMinRenderTargetHeight = GR_INVAL_GLINT;
326 GLint maxRenderSize;
reed@google.comac20fb92011-01-12 17:14:53 +0000327 GR_GL_GetIntegerv(GR_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000328
reed@google.comeeeb5a02010-12-23 15:12:59 +0000329 if (gPrintStartupSpew) {
330 GrPrintf("Small height FBO texture experiments\n");
331 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000332
333 for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000334 GLuint w = maxRenderSize;
335 GLuint h = i;
336 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000337 if (gPrintStartupSpew) {
338 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
339 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000340 fMinRenderTargetHeight = i;
341 break;
342 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000343 if (gPrintStartupSpew) {
344 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
345 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000346 }
347 }
348 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
349
reed@google.comeeeb5a02010-12-23 15:12:59 +0000350 if (gPrintStartupSpew) {
351 GrPrintf("Small width FBO texture experiments\n");
352 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000353 fMinRenderTargetWidth = GR_MAX_GLUINT;
bsalomon@google.com0748f212011-02-01 22:56:16 +0000354 for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000355 GLuint w = i;
356 GLuint h = maxRenderSize;
357 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000358 if (gPrintStartupSpew) {
359 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
360 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000361 fMinRenderTargetWidth = i;
362 break;
363 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000364 if (gPrintStartupSpew) {
365 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
366 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000367 }
368 }
369 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
370
reed@google.com02a7e6c2011-01-28 21:21:49 +0000371 GR_GL_GetIntegerv(GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000372}
373
374GrGpuGL::~GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000375#if GR_GL_NO_CLIENT_SIDE_ARRAYS
376 GrSafeUnref(fClientArrayVB);
377 GrSafeUnref(fClientArrayIB);
378#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000379}
380
381void GrGpuGL::resetContextHelper() {
382// We detect cases when blending is effectively off
383 fHWBlendDisabled = false;
384 GR_GL(Enable(GL_BLEND));
385
386 // this is always disabled
387 GR_GL(Disable(GL_CULL_FACE));
388
389 GR_GL(Disable(GL_DITHER));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000390#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000391 GR_GL(Disable(GL_LINE_SMOOTH));
392 GR_GL(Disable(GL_POINT_SMOOTH));
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000393 GR_GL(Disable(GL_MULTISAMPLE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000394#endif
395
396 // we only ever use lines in hairline mode
397 GR_GL(LineWidth(1));
398
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000399 // invalid
400 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000401
402 fHWDrawState.fFlagBits = 0;
403
404 // illegal values
405 fHWDrawState.fSrcBlend = (BlendCoeff)-1;
406 fHWDrawState.fDstBlend = (BlendCoeff)-1;
407 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000408
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000409 fHWDrawState.fViewMatrix.setScale(GR_ScalarMax, GR_ScalarMax); // illegal
bsalomon@google.com316f99232011-01-13 21:28:12 +0000410
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000411 for (int s = 0; s < kNumStages; ++s) {
412 fHWDrawState.fTextures[s] = NULL;
413 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
414 -GR_ScalarMax,
415 true);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000416 fHWDrawState.fTextureMatrices[s].setScale(GR_ScalarMax, GR_ScalarMax);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000417 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000418
reed@google.comac10a2d2010-12-22 21:39:39 +0000419 GR_GL(Scissor(0,0,0,0));
420 fHWBounds.fScissorRect.setLTRB(0,0,0,0);
421 fHWBounds.fScissorEnabled = false;
422 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000423 fHWBounds.fViewportRect.setLTRB(-1,-1,-1,-1);
reed@google.comac10a2d2010-12-22 21:39:39 +0000424
reed@google.comac10a2d2010-12-22 21:39:39 +0000425 // disabling the stencil test also disables
426 // stencil buffer writes
427 GR_GL(Disable(GL_STENCIL_TEST));
428 GR_GL(StencilMask(0xffffffff));
429 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
430 fHWDrawState.fReverseFill = false;
431 fHWDrawState.fStencilPass = kNone_StencilPass;
432 fHWStencilClip = false;
433
434 fHWGeometryState.fIndexBuffer = NULL;
435 fHWGeometryState.fVertexBuffer = NULL;
436 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
437 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000438 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000439
440 fHWDrawState.fRenderTarget = NULL;
441}
442
443void GrGpuGL::resetContext() {
444 INHERITED::resetContext();
445 resetContextHelper();
446}
447
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000448#if GR_GL_NO_CLIENT_SIDE_ARRAYS
449void GrGpuGL::putClientVertexDataInBuffer(const void* vertexData, size_t vertexDataSize) {
450 static const size_t MIN_VB_SIZE = 1 << 11;
451 static const int MAX_OVERSIZE_VB_DRAWS = 100;
452
453 if (NULL != vertexData) {
454 size_t currMinVBSize = GrMax(MIN_VB_SIZE, vertexDataSize);
455 // if we don't have a VB, its too small, or too big, create a new one
456 if (NULL == fClientArrayVB ||
457 fClientArrayVB->size() < currMinVBSize ||
458 (fOversizeVBDrawCnt >= MAX_OVERSIZE_VB_DRAWS &&
459 currMinVBSize == MIN_VB_SIZE &&
460 fClientArrayVB->size() > MIN_VB_SIZE)) {
461
462 if (fHWGeometryState.fVertexBuffer == fClientArrayVB) {
463 fHWGeometryState.fVertexBuffer = NULL;
464 fHWGeometryState.fArrayPtrsDirty = true;
465 }
466 GrSafeUnref(fClientArrayVB);
467 fClientArrayVB = (GrGLVertexBuffer*)createVertexBuffer(currMinVBSize, true);
468 fOversizeVBDrawCnt = 0;
469 GrPrintf("Realloc VB 0%08x\n", currMinVBSize);
470 }
471 fClientArrayVB->updateData(vertexData, vertexDataSize);
472 if (currMinVBSize == MIN_VB_SIZE && fClientArrayVB->size() > MIN_VB_SIZE) {
473 ++fOversizeVBDrawCnt;
474 }
475 }
476}
477
478void GrGpuGL::putClientIndexDataInBuffer(const void* indexData, size_t indexDataSize) {
479 static const size_t MIN_IB_SIZE = 1 << 8;
480 static const int MAX_OVERSIZE_IB_DRAWS = 100;
481
482 if (NULL != indexData) {
483 size_t currMinIBSize = GrMax(MIN_IB_SIZE, indexDataSize);
484 // if we don't have a IB, its too small, or too big, create a new one
485 if (NULL == fClientArrayIB ||
486 fClientArrayIB->size() < currMinIBSize ||
487 (fOversizeIBDrawCnt >= MAX_OVERSIZE_IB_DRAWS &&
488 currMinIBSize == MIN_IB_SIZE &&
489 fClientArrayIB->size() > MIN_IB_SIZE)) {
490
491 if (fHWGeometryState.fIndexBuffer == fClientArrayIB) {
492 fHWGeometryState.fIndexBuffer = NULL;
493 }
494 GrSafeUnref(fClientArrayIB);
495 fClientArrayIB = (GrGLIndexBuffer*)createIndexBuffer(currMinIBSize, true);
496 fOversizeIBDrawCnt = 0;
497 }
498 fClientArrayIB->updateData(indexData, indexDataSize);
499 if (currMinIBSize == MIN_IB_SIZE && fClientArrayIB->size() > MIN_IB_SIZE) {
500 ++fOversizeIBDrawCnt;
501 }
502 }
503}
504#endif
505
reed@google.comac10a2d2010-12-22 21:39:39 +0000506GrRenderTarget* GrGpuGL::createPlatformRenderTarget(
507 intptr_t platformRenderTarget,
508 int width, int height) {
509 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
510 rtIDs.fStencilRenderbufferID = 0;
511 rtIDs.fMSColorRenderbufferID = 0;
512 rtIDs.fTexFBOID = 0;
513 rtIDs.fOwnIDs = false;
514
515 GrIRect viewport;
516
517 // viewport is in GL coords (top >= bottom)
518 viewport.setLTRB(0, height, width, 0);
519
520 rtIDs.fRTFBOID = (GLuint)platformRenderTarget;
521 rtIDs.fTexFBOID = (GLuint)platformRenderTarget;
522
523 GrGLRenderTarget* rt = new GrGLRenderTarget(rtIDs, viewport, NULL, this);
524
525 return rt;
526}
527
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000528GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000529
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000530 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000531
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000532 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&rtIDs.fRTFBOID);
533 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
534 rtIDs.fMSColorRenderbufferID = 0;
535 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000536
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000537 GLint vp[4];
538 GR_GL_GetIntegerv(GL_VIEWPORT, vp);
539 GrIRect viewportRect;
540 viewportRect.setLTRB(vp[0],
541 vp[1] + vp[3],
542 vp[0] + vp[2],
543 vp[1]);
544 rtIDs.fOwnIDs = false;
545
546 return new GrGLRenderTarget(rtIDs,
547 viewportRect,
548 NULL,
549 this);
550}
551
bsalomon@google.com5782d712011-01-21 21:03:59 +0000552///////////////////////////////////////////////////////////////////////////////
553
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000554// defines stencil formats from more to less preferred
reed@google.com63100f92011-01-18 21:32:14 +0000555GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = {
556 GR_STENCIL_INDEX8,
557
558#if GR_SUPPORT_GLDESKTOP
559 GR_STENCIL_INDEX16,
560#endif
561
562 GR_DEPTH24_STENCIL8,
563 GR_STENCIL_INDEX4,
564
565#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000566 GL_STENCIL_INDEX,
567 GR_DEPTH_STENCIL,
568#endif
569};
570
571// good to set a break-point here to know when createTexture fails
572static GrTexture* return_null_texture() {
573// GrAssert(!"null texture");
574 return NULL;
575}
576
577#if GR_DEBUG
578static size_t as_size_t(int x) {
579 return x;
580}
581#endif
582
reed@google.comac10a2d2010-12-22 21:39:39 +0000583GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
584 const void* srcData, size_t rowBytes) {
585
586#if GR_COLLECT_STATS
587 ++fStats.fTextureCreateCnt;
588#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000589
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000590 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000591
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000592 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
593 GL_NEAREST,
594 GL_CLAMP_TO_EDGE,
595 GL_CLAMP_TO_EDGE
596 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000597
reed@google.comac10a2d2010-12-22 21:39:39 +0000598 GrGLTexture::GLTextureDesc glDesc;
599 GLenum internalFormat;
600
601 glDesc.fContentWidth = desc.fWidth;
602 glDesc.fContentHeight = desc.fHeight;
603 glDesc.fAllocWidth = desc.fWidth;
604 glDesc.fAllocHeight = desc.fHeight;
605 glDesc.fFormat = desc.fFormat;
606
607 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
608 if (!canBeTexture(desc.fFormat,
609 &internalFormat,
610 &glDesc.fUploadFormat,
611 &glDesc.fUploadType)) {
612 return return_null_texture();
613 }
614
615 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
616 GLint samples = fAASamples[desc.fAALevel];
617 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
618 GrPrintf("AA RT requested but not supported on this platform.");
619 }
620
621 GR_GL(GenTextures(1, &glDesc.fTextureID));
622 if (!glDesc.fTextureID) {
623 return return_null_texture();
624 }
625
626 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
627
628 /*
629 * check if our srcData has extra bytes past each row. If so, we need
630 * to trim those off here, since GL doesn't let us pass the rowBytes as
631 * a parameter to glTexImage2D
632 */
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000633#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000634 if (srcData) {
635 GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH,
636 rowBytes / glDesc.fUploadByteCount));
637 }
638#else
639 GrAutoSMalloc<128 * 128> trimStorage;
640 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
641 if (srcData && (trimRowBytes < rowBytes)) {
642 size_t trimSize = desc.fHeight * trimRowBytes;
643 trimStorage.realloc(trimSize);
644 // now copy the data into our new storage, skipping the trailing bytes
645 const char* src = (const char*)srcData;
646 char* dst = (char*)trimStorage.get();
647 for (uint32_t y = 0; y < desc.fHeight; y++) {
648 memcpy(dst, src, trimRowBytes);
649 src += rowBytes;
650 dst += trimRowBytes;
651 }
652 // now point srcData to our trimmed version
653 srcData = trimStorage.get();
654 }
655#endif
656
reed@google.comac10a2d2010-12-22 21:39:39 +0000657 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000658 if (!this->npotRenderTargetSupport()) {
659 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
660 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
661 }
662
reed@google.comac10a2d2010-12-22 21:39:39 +0000663 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
664 glDesc.fAllocWidth);
665 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
666 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000667 } else if (!this->npotTextureSupport()) {
668 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
669 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000670 }
671
672 GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000673 GR_GL(TexParameteri(GL_TEXTURE_2D,
674 GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000675 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000676 GR_GL(TexParameteri(GL_TEXTURE_2D,
677 GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000678 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000679 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000680 GL_TEXTURE_WRAP_S,
681 DEFAULT_PARAMS.fWrapS));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000682 GR_GL(TexParameteri(GL_TEXTURE_2D,
683 GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000684 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000685
686 GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
687 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
688 supports8BitPalette()) {
689 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
690 GrAssert(desc.fWidth == glDesc.fAllocWidth);
691 GrAssert(desc.fHeight == glDesc.fAllocHeight);
692 GLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
693 kColorTableSize;
694 GR_GL(CompressedTexImage2D(GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
695 glDesc.fAllocWidth, glDesc.fAllocHeight,
696 0, imageSize, srcData));
697 GrGL_RestoreResetRowLength();
698 } else {
699 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
700 glDesc.fAllocHeight != desc.fHeight)) {
701 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat,
702 glDesc.fAllocWidth, glDesc.fAllocHeight,
703 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
704 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
705 desc.fHeight, glDesc.fUploadFormat,
706 glDesc.fUploadType, srcData));
707 GrGL_RestoreResetRowLength();
708
709 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
710 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
711 uint32_t maxTexels = extraW * extraH;
712 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
713 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
714
715 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
716
717 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
718 if (extraH) {
719 uint8_t* lastRowStart = (uint8_t*) srcData +
720 (desc.fHeight - 1) * rowSize;
721 uint8_t* extraRowStart = (uint8_t*)texels.get();
722
723 for (uint32_t i = 0; i < extraH; ++i) {
724 memcpy(extraRowStart, lastRowStart, rowSize);
725 extraRowStart += rowSize;
726 }
727 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
728 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
729 texels.get()));
730 }
731 if (extraW) {
732 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
733 uint8_t* extraTexel = (uint8_t*)texels.get();
734 for (uint32_t j = 0; j < desc.fHeight; ++j) {
735 for (uint32_t i = 0; i < extraW; ++i) {
736 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
737 extraTexel += glDesc.fUploadByteCount;
738 }
739 edgeTexel += rowSize;
740 }
741 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
742 desc.fHeight, glDesc.fUploadFormat,
743 glDesc.fUploadType, texels.get()));
744 }
745 if (extraW && extraH) {
746 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
747 - glDesc.fUploadByteCount;
748 uint8_t* extraTexel = (uint8_t*)texels.get();
749 for (uint32_t i = 0; i < extraW*extraH; ++i) {
750 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
751 extraTexel += glDesc.fUploadByteCount;
752 }
753 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
754 extraW, extraH, glDesc.fUploadFormat,
755 glDesc.fUploadType, texels.get()));
756 }
757
758 } else {
759 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
760 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
761 glDesc.fUploadType, srcData));
762 GrGL_RestoreResetRowLength();
763 }
764 }
765
766 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
767
768 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
769 rtIDs.fStencilRenderbufferID = 0;
770 rtIDs.fMSColorRenderbufferID = 0;
771 rtIDs.fRTFBOID = 0;
772 rtIDs.fTexFBOID = 0;
773 rtIDs.fOwnIDs = true;
774 GLenum msColorRenderbufferFormat = -1;
775
776 if (renderTarget) {
777#if GR_COLLECT_STATS
778 ++fStats.fRenderTargetCreateCnt;
779#endif
780 bool failed = true;
781 GLenum status;
782 GLint err;
783
784 // If need have both RT flag and srcData we have
785 // to invert the data before uploading because FBO
786 // will be rendered bottom up
787 GrAssert(NULL == srcData);
788 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
789
790 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fTexFBOID));
791 GrAssert(rtIDs.fTexFBOID);
792
793 // If we are using multisampling and any extension other than the IMG
794 // one we will create two FBOs. We render to one and then resolve to
795 // the texture bound to the other. The IMG extension does an implicit
796 // resolve.
797 if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
798 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fRTFBOID));
799 GrAssert(0 != rtIDs.fRTFBOID);
800 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
801 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
802 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
803 GR_GLEXT(fExts,
804 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
805 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
806 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
807 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000808 return return_null_texture();
809 }
810 } else {
811 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
812 }
813 int attempts = 1;
814 if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
815 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
816 GrAssert(0 != rtIDs.fStencilRenderbufferID);
817 attempts = GR_ARRAY_COUNT(GR_GL_STENCIL_FORMAT_ARRAY);
818 }
819
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000820 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000821 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000822 // (seems unlikely)
reed@google.comac10a2d2010-12-22 21:39:39 +0000823 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000824
825 err = ~GL_NO_ERROR;
826 for (int i = 0; i < attempts; ++i) {
827 if (rtIDs.fStencilRenderbufferID) {
828 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
829 rtIDs.fStencilRenderbufferID));
830 if (samples > 1) {
831 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
832 GR_RENDERBUFFER,
833 samples,
834 GR_GL_STENCIL_FORMAT_ARRAY[i],
835 glDesc.fAllocWidth,
836 glDesc.fAllocHeight));
837 } else {
838 GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
839 GR_RENDERBUFFER,
840 GR_GL_STENCIL_FORMAT_ARRAY[i],
841 glDesc.fAllocWidth,
842 glDesc.fAllocHeight));
843 }
844 err = glGetError();
845 if (err != GL_NO_ERROR) {
846 continue;
847 }
848 }
849 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
850 GrAssert(samples > 1);
851 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
852 rtIDs.fMSColorRenderbufferID));
853 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
854 GR_RENDERBUFFER,
855 samples,
856 msColorRenderbufferFormat,
857 glDesc.fAllocWidth,
858 glDesc.fAllocHeight));
859 err = glGetError();
860 if (err != GL_NO_ERROR) {
861 continue;
862 }
863 }
864 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
865
866#if GR_COLLECT_STATS
867 ++fStats.fRenderTargetChngCnt;
868#endif
869 if (kIMG_MSFBO == fMSFBOType && samples > 1) {
870 GR_GLEXT(fExts, FramebufferTexture2DMultisample(
871 GR_FRAMEBUFFER,
872 GR_COLOR_ATTACHMENT0,
873 GL_TEXTURE_2D,
874 glDesc.fTextureID,
875 0,
876 samples));
877
878 } else {
879 GR_GLEXT(fExts, FramebufferTexture2D(GR_FRAMEBUFFER,
880 GR_COLOR_ATTACHMENT0,
881 GL_TEXTURE_2D,
882 glDesc.fTextureID, 0));
883 }
884 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
885 GLenum status = GR_GLEXT(fExts,
886 CheckFramebufferStatus(GR_FRAMEBUFFER));
887 if (status != GR_FRAMEBUFFER_COMPLETE) {
888 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
889 status, desc.fWidth, desc.fHeight);
890 continue;
891 }
892 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
893 #if GR_COLLECT_STATS
894 ++fStats.fRenderTargetChngCnt;
895 #endif
896 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
897 GR_COLOR_ATTACHMENT0,
898 GR_RENDERBUFFER,
899 rtIDs.fMSColorRenderbufferID));
900
901 }
902 if (rtIDs.fStencilRenderbufferID) {
903 // bind the stencil to rt fbo if present, othewise the tex fbo
904 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
905 GR_STENCIL_ATTACHMENT,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000906 GR_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000907 rtIDs.fStencilRenderbufferID));
908 }
909 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
910
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000911#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000912 // On some implementations you have to be bound as DEPTH_STENCIL.
913 // (Even binding to DEPTH and STENCIL separately with the same
914 // buffer doesn't work.)
915 if (rtIDs.fStencilRenderbufferID &&
916 status != GR_FRAMEBUFFER_COMPLETE) {
917 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
918 GR_STENCIL_ATTACHMENT,
919 GR_RENDERBUFFER,
920 0));
921 GR_GLEXT(fExts,
922 FramebufferRenderbuffer(GR_FRAMEBUFFER,
923 GR_DEPTH_STENCIL_ATTACHMENT,
924 GR_RENDERBUFFER,
925 rtIDs.fStencilRenderbufferID));
926 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
927 }
928#endif
929 if (status != GR_FRAMEBUFFER_COMPLETE) {
930 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
931 status, desc.fWidth, desc.fHeight);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000932#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000933 if (rtIDs.fStencilRenderbufferID) {
934 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
935 GR_DEPTH_STENCIL_ATTACHMENT,
936 GR_RENDERBUFFER,
937 0));
938 }
939#endif
940 continue;
941 }
942 // we're successful!
943 failed = false;
944 break;
945 }
946 if (failed) {
947 if (rtIDs.fStencilRenderbufferID) {
948 GR_GLEXT(fExts,
949 DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
950 }
951 if (rtIDs.fMSColorRenderbufferID) {
952 GR_GLEXT(fExts,
953 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
954 }
955 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
956 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
957 }
958 if (rtIDs.fTexFBOID) {
959 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
960 }
961 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
962 return return_null_texture();
963 }
964 }
965#ifdef TRACE_TEXTURE_CREATION
966 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
967 tex->fTextureID, width, height, tex->fUploadByteCount);
968#endif
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000969 GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, DEFAULT_PARAMS, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000970
971 if (0 != rtIDs.fTexFBOID) {
972 GrRenderTarget* rt = tex->asRenderTarget();
973 // We've messed with FBO state but may not have set the correct viewport
974 // so just dirty the rendertarget state to force a resend.
975 fHWDrawState.fRenderTarget = NULL;
976
977 // clear the new stencil buffer if we have one
978 if (!(desc.fFlags & kNoPathRendering_TextureFlag)) {
979 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
980 fCurrDrawState.fRenderTarget = rt;
981 eraseStencil(0, ~0);
982 fCurrDrawState.fRenderTarget = rtSave;
983 }
984 }
985 return tex;
986}
987
reed@google.comac10a2d2010-12-22 21:39:39 +0000988GrVertexBuffer* GrGpuGL::createVertexBuffer(uint32_t size, bool dynamic) {
989 GLuint id;
990 GR_GL(GenBuffers(1, &id));
991 if (id) {
992 GR_GL(BindBuffer(GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000993 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000994 GrGLClearErr();
995 // make sure driver can allocate memory for this buffer
996 GR_GL_NO_ERR(BufferData(GL_ARRAY_BUFFER, size, NULL,
997 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
998 if (glGetError() != GL_NO_ERROR) {
999 GR_GL(DeleteBuffers(1, &id));
1000 // deleting bound buffer does implicit bind to 0
1001 fHWGeometryState.fVertexBuffer = NULL;
1002 return NULL;
1003 }
1004 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this,
1005 size, dynamic);
1006 fHWGeometryState.fVertexBuffer = vertexBuffer;
1007 return vertexBuffer;
1008 }
1009 return NULL;
1010}
1011
1012GrIndexBuffer* GrGpuGL::createIndexBuffer(uint32_t size, bool dynamic) {
1013 GLuint id;
1014 GR_GL(GenBuffers(1, &id));
1015 if (id) {
1016 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, id));
1017 GrGLClearErr();
1018 // make sure driver can allocate memory for this buffer
1019 GR_GL_NO_ERR(BufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1020 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
1021 if (glGetError() != GL_NO_ERROR) {
1022 GR_GL(DeleteBuffers(1, &id));
1023 // deleting bound buffer does implicit bind to 0
1024 fHWGeometryState.fIndexBuffer = NULL;
1025 return NULL;
1026 }
1027 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this,
1028 size, dynamic);
1029 fHWGeometryState.fIndexBuffer = indexBuffer;
1030 return indexBuffer;
1031 }
1032 return NULL;
1033}
1034
reed@google.comac10a2d2010-12-22 21:39:39 +00001035void GrGpuGL::flushScissor(const GrIRect* rect) {
1036 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1037 const GrIRect& vp =
1038 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1039
1040 if (NULL != rect &&
1041 rect->contains(vp)) {
1042 rect = NULL;
1043 }
1044
1045 if (NULL != rect) {
1046 GrIRect scissor;
1047 // viewport is already in GL coords
1048 // create a scissor in GL coords (top > bottom)
1049 scissor.setLTRB(vp.fLeft + rect->fLeft,
1050 vp.fTop - rect->fTop,
1051 vp.fLeft + rect->fRight,
1052 vp.fTop - rect->fBottom);
1053
1054 if (fHWBounds.fScissorRect != scissor) {
1055 GR_GL(Scissor(scissor.fLeft, scissor.fBottom,
1056 scissor.width(), -scissor.height()));
1057 fHWBounds.fScissorRect = scissor;
1058 }
1059
1060 if (!fHWBounds.fScissorEnabled) {
1061 GR_GL(Enable(GL_SCISSOR_TEST));
1062 fHWBounds.fScissorEnabled = true;
1063 }
1064 } else {
1065 if (fHWBounds.fScissorEnabled) {
1066 GR_GL(Disable(GL_SCISSOR_TEST));
1067 fHWBounds.fScissorEnabled = false;
1068 }
1069 }
1070}
1071
reed@google.comac10a2d2010-12-22 21:39:39 +00001072void GrGpuGL::eraseColor(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001073 if (NULL == fCurrDrawState.fRenderTarget) {
1074 return;
1075 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001076 flushRenderTarget();
1077 if (fHWBounds.fScissorEnabled) {
1078 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001079 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001080 }
1081 GR_GL(ColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE));
1082 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1083 GrColorUnpackG(color)/255.f,
1084 GrColorUnpackB(color)/255.f,
1085 GrColorUnpackA(color)/255.f));
1086 GR_GL(Clear(GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001087 fWriteMaskChanged = true;
1088}
1089
1090void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001091 if (NULL == fCurrDrawState.fRenderTarget) {
1092 return;
1093 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 flushRenderTarget();
1095 if (fHWBounds.fScissorEnabled) {
1096 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001097 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001098 }
1099 GR_GL(StencilMask(mask));
1100 GR_GL(ClearStencil(value));
1101 GR_GL(Clear(GL_STENCIL_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001102 fWriteMaskChanged = true;
1103}
1104
1105void GrGpuGL::eraseStencilClip() {
1106 GLint stencilBitCount;
reed@google.comac20fb92011-01-12 17:14:53 +00001107 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001108 GrAssert(stencilBitCount > 0);
1109 GLint clipStencilMask = (1 << (stencilBitCount - 1));
1110 eraseStencil(0, clipStencilMask);
1111}
1112
1113void GrGpuGL::forceRenderTargetFlush() {
1114 flushRenderTarget();
1115}
1116
1117bool GrGpuGL::readPixels(int left, int top, int width, int height,
1118 GrTexture::PixelConfig config, void* buffer) {
1119 GLenum internalFormat; // we don't use this for glReadPixels
1120 GLenum format;
1121 GLenum type;
1122 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1123 return false;
1124 }
1125
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001126 if (NULL == fCurrDrawState.fRenderTarget) {
1127 return false;
1128 }
1129 flushRenderTarget();
1130
reed@google.comac10a2d2010-12-22 21:39:39 +00001131 const GrIRect& vp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1132
1133 // Brian says that viewport rects are already upside down (grrrrr)
bsalomon@google.com316f99232011-01-13 21:28:12 +00001134 GR_GL(ReadPixels(left, -vp.height() - top - height, width, height,
1135 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001136
1137 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1138 // API presents top-to-bottom
1139 {
1140 size_t stride = width * GrTexture::BytesPerPixel(config);
1141 GrAutoMalloc rowStorage(stride);
1142 void* tmp = rowStorage.get();
1143
1144 const int halfY = height >> 1;
1145 char* top = reinterpret_cast<char*>(buffer);
1146 char* bottom = top + (height - 1) * stride;
1147 for (int y = 0; y < halfY; y++) {
1148 memcpy(tmp, top, stride);
1149 memcpy(top, bottom, stride);
1150 memcpy(bottom, tmp, stride);
1151 top += stride;
1152 bottom -= stride;
1153 }
1154 }
1155 return true;
1156}
1157
1158void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001159
1160 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1161
reed@google.comac10a2d2010-12-22 21:39:39 +00001162 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1163 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
1164 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
1165 #if GR_COLLECT_STATS
1166 ++fStats.fRenderTargetChngCnt;
1167 #endif
1168 rt->setDirty(true);
1169 #if GR_DEBUG
1170 GLenum status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
1171 if (status != GR_FRAMEBUFFER_COMPLETE) {
1172 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1173 }
1174 #endif
1175 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
1176 const GrIRect& vp = rt->viewport();
1177 fRenderTargetChanged = true;
1178 if (fHWBounds.fViewportRect != vp) {
1179 GR_GL(Viewport(vp.fLeft,
1180 vp.fBottom,
1181 vp.width(),
1182 -vp.height()));
1183 fHWBounds.fViewportRect = vp;
1184 }
1185 }
1186}
1187
1188GLenum gPrimitiveType2GLMode[] = {
1189 GL_TRIANGLES,
1190 GL_TRIANGLE_STRIP,
1191 GL_TRIANGLE_FAN,
1192 GL_POINTS,
1193 GL_LINES,
1194 GL_LINE_STRIP
1195};
1196
1197void GrGpuGL::drawIndexedHelper(PrimitiveType type,
1198 uint32_t startVertex,
1199 uint32_t startIndex,
1200 uint32_t vertexCount,
1201 uint32_t indexCount) {
1202 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1203
1204 GLvoid* indices = (GLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001205
1206#if GR_GL_NO_CLIENT_SIDE_ARRAYS
1207 if (kBuffer_GeometrySrcType != fGeometrySrc.fIndexSrc) {
1208 // we accounted for the startIndex when shoving data into a vb
1209 indices = NULL;
1210 }
1211#else
reed@google.comac10a2d2010-12-22 21:39:39 +00001212 if (kReserved_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1213 indices = (GLvoid*)((intptr_t)indices + (intptr_t)fIndices.get());
1214 } else if (kArray_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1215 indices = (GLvoid*)((intptr_t)indices +
1216 (intptr_t)fGeometrySrc.fIndexArray);
1217 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001218#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001219
1220 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1221 GL_UNSIGNED_SHORT, indices));
1222}
1223
1224void GrGpuGL::drawNonIndexedHelper(PrimitiveType type,
1225 uint32_t startVertex,
1226 uint32_t vertexCount) {
1227 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1228
1229 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1230}
1231
reed@google.comac10a2d2010-12-22 21:39:39 +00001232void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1233 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1234
1235 if (NULL != rt && rt->needsResolve()) {
1236 GrAssert(kNone_MSFBO != fMSFBOType);
1237 GrAssert(rt->textureFBOID() != rt->renderFBOID());
1238 GR_GLEXT(fExts, BindFramebuffer(GR_READ_FRAMEBUFFER,
1239 rt->renderFBOID()));
1240 GR_GLEXT(fExts, BindFramebuffer(GR_DRAW_FRAMEBUFFER,
1241 rt->textureFBOID()));
1242 #if GR_COLLECT_STATS
1243 ++fStats.fRenderTargetChngCnt;
1244 #endif
1245 // make sure we go through set render target
1246 fHWDrawState.fRenderTarget = NULL;
1247
1248 GLint left = 0;
1249 GLint right = texture->contentWidth();
1250 // we will have rendered to the top of the FBO.
1251 GLint top = texture->allocHeight();
1252 GLint bottom = texture->allocHeight() - texture->contentHeight();
1253 if (kApple_MSFBO == fMSFBOType) {
1254 GR_GL(Enable(GL_SCISSOR_TEST));
1255 GR_GL(Scissor(left, bottom, right-left, top-bottom));
1256 GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
1257 fHWBounds.fScissorRect.setEmpty();
1258 fHWBounds.fScissorEnabled = true;
1259 } else {
1260 GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
1261 left, bottom, right, top,
1262 GL_COLOR_BUFFER_BIT, GL_NEAREST));
1263 }
1264 rt->setDirty(false);
1265
1266 }
1267}
1268
1269void GrGpuGL::flushStencil() {
1270
1271 // use stencil for clipping if clipping is enabled and the clip
1272 // has been written into the stencil.
1273 bool stencilClip = fClipState.fClipInStencil &&
1274 (kClip_StateBit & fCurrDrawState.fFlagBits);
1275 bool stencilChange =
1276 fWriteMaskChanged ||
1277 fHWStencilClip != stencilClip ||
1278 fHWDrawState.fStencilPass != fCurrDrawState.fStencilPass ||
1279 (kNone_StencilPass != fCurrDrawState.fStencilPass &&
1280 (StencilPass)kSetClip_StencilPass != fCurrDrawState.fStencilPass &&
1281 fHWDrawState.fReverseFill != fCurrDrawState.fReverseFill);
1282
1283 if (stencilChange) {
1284 GLint stencilBitCount;
1285 GLint clipStencilMask;
1286 GLint pathStencilMask;
reed@google.comac20fb92011-01-12 17:14:53 +00001287 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001288 GrAssert(stencilBitCount > 0 ||
1289 kNone_StencilPass == fCurrDrawState.fStencilPass);
1290 clipStencilMask = (1 << (stencilBitCount - 1));
1291 pathStencilMask = clipStencilMask - 1;
1292 switch (fCurrDrawState.fStencilPass) {
1293 case kNone_StencilPass:
1294 if (stencilClip) {
1295 GR_GL(Enable(GL_STENCIL_TEST));
1296 GR_GL(StencilFunc(GL_EQUAL,
1297 clipStencilMask,
1298 clipStencilMask));
1299 GR_GL(StencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
1300 } else {
1301 GR_GL(Disable(GL_STENCIL_TEST));
1302 }
1303 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1304 if (!fSingleStencilPassForWinding) {
1305 GR_GL(Disable(GL_CULL_FACE));
1306 }
1307 break;
1308 case kEvenOddStencil_StencilPass:
1309 GR_GL(Enable(GL_STENCIL_TEST));
1310 if (stencilClip) {
1311 GR_GL(StencilFunc(GL_EQUAL, clipStencilMask, clipStencilMask));
1312 } else {
1313 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1314 }
1315 GR_GL(StencilMask(pathStencilMask));
1316 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1317 GR_GL(StencilOp(GL_KEEP, GL_INVERT, GL_INVERT));
1318 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1319 if (!fSingleStencilPassForWinding) {
1320 GR_GL(Disable(GL_CULL_FACE));
1321 }
1322 break;
1323 case kEvenOddColor_StencilPass: {
1324 GR_GL(Enable(GL_STENCIL_TEST));
1325 GLint funcRef = 0;
1326 GLuint funcMask = pathStencilMask;
1327 if (stencilClip) {
1328 funcRef |= clipStencilMask;
1329 funcMask |= clipStencilMask;
1330 }
1331 if (!fCurrDrawState.fReverseFill) {
1332 funcRef |= pathStencilMask;
1333 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001334 GR_GL(StencilFunc(GL_EQUAL, funcRef, funcMask));
1335 GR_GL(StencilMask(pathStencilMask));
reed@google.comac10a2d2010-12-22 21:39:39 +00001336 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1337 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1338 if (!fSingleStencilPassForWinding) {
1339 GR_GL(Disable(GL_CULL_FACE));
1340 }
1341 } break;
1342 case kWindingStencil1_StencilPass:
1343 GR_GL(Enable(GL_STENCIL_TEST));
1344 if (fHasStencilWrap) {
1345 if (stencilClip) {
1346 GR_GL(StencilFunc(GL_EQUAL,
1347 clipStencilMask,
1348 clipStencilMask));
1349 } else {
1350 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1351 }
1352 if (fSingleStencilPassForWinding) {
1353 GR_GL(StencilOpSeparate(GL_FRONT, GL_KEEP,
1354 GL_INCR_WRAP, GL_INCR_WRAP));
1355 GR_GL(StencilOpSeparate(GL_BACK, GL_KEEP,
1356 GL_DECR_WRAP, GL_DECR_WRAP));
1357 } else {
1358 GR_GL(StencilOp(GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP));
1359 GR_GL(Enable(GL_CULL_FACE));
1360 GR_GL(CullFace(GL_BACK));
1361 }
1362 } else {
1363 // If we don't have wrap then we use the Func to detect
1364 // values that would wrap (0 on decr and mask on incr). We
1365 // make the func fail on these values and use the sfail op
1366 // to effectively wrap by inverting.
1367 // This applies whether we are doing a two-pass (front faces
1368 // followed by back faces) or a single pass (separate func/op)
1369
1370 // Note that in the case where we are also using stencil to
1371 // clip this means we will write into the path bits in clipped
1372 // out pixels. We still apply the clip bit in the color pass
1373 // stencil func so we don't draw color outside the clip.
1374 // We also will clear the stencil bits in clipped pixels by
1375 // using zero in the sfail op with write mask set to the
1376 // path mask.
1377 GR_GL(Enable(GL_STENCIL_TEST));
1378 if (fSingleStencilPassForWinding) {
1379 GR_GL(StencilFuncSeparate(GL_FRONT,
1380 GL_NOTEQUAL,
1381 pathStencilMask,
1382 pathStencilMask));
1383 GR_GL(StencilFuncSeparate(GL_BACK,
1384 GL_NOTEQUAL,
1385 0x0,
1386 pathStencilMask));
1387 GR_GL(StencilOpSeparate(GL_FRONT, GL_INVERT,
1388 GL_INCR, GL_INCR));
1389 GR_GL(StencilOpSeparate(GL_BACK, GL_INVERT,
1390 GL_DECR, GL_DECR));
1391 } else {
1392 GR_GL(StencilFunc(GL_NOTEQUAL,
1393 pathStencilMask,
1394 pathStencilMask));
1395 GR_GL(StencilOp(GL_INVERT, GL_INCR, GL_INCR));
1396 GR_GL(Enable(GL_CULL_FACE));
1397 GR_GL(CullFace(GL_BACK));
1398 }
1399 }
1400 GR_GL(StencilMask(pathStencilMask));
1401 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1402 break;
1403 case kWindingStencil2_StencilPass:
1404 GrAssert(!fSingleStencilPassForWinding);
1405 GR_GL(Enable(GL_STENCIL_TEST));
1406 if (fHasStencilWrap) {
1407 if (stencilClip) {
1408 GR_GL(StencilFunc(GL_EQUAL,
1409 clipStencilMask,
1410 clipStencilMask));
1411 } else {
1412 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1413 }
1414 GR_GL(StencilOp(GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP));
1415 } else {
1416 GR_GL(StencilFunc(GL_NOTEQUAL, 0x0, pathStencilMask));
1417 GR_GL(StencilOp(GL_INVERT, GL_DECR, GL_DECR));
1418 }
1419 GR_GL(StencilMask(pathStencilMask));
1420 GR_GL(Enable(GL_CULL_FACE));
1421 GR_GL(CullFace(GL_FRONT));
1422 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1423 break;
1424 case kWindingColor_StencilPass: {
1425 GR_GL(Enable(GL_STENCIL_TEST));
1426 GLint funcRef = 0;
1427 GLuint funcMask = pathStencilMask;
1428 GLenum funcFunc;
1429 if (stencilClip) {
1430 funcRef |= clipStencilMask;
1431 funcMask |= clipStencilMask;
1432 }
1433 if (fCurrDrawState.fReverseFill) {
1434 funcFunc = GL_EQUAL;
1435 } else {
1436 funcFunc = GL_LESS;
1437 }
1438 GR_GL(StencilFunc(funcFunc, funcRef, funcMask));
1439 GR_GL(StencilMask(pathStencilMask));
1440 // must zero in sfail because winding w/o wrap will write
1441 // path stencil bits in clipped out pixels
1442 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1443 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1444 if (!fSingleStencilPassForWinding) {
1445 GR_GL(Disable(GL_CULL_FACE));
1446 }
1447 } break;
1448 case kSetClip_StencilPass:
1449 GR_GL(Enable(GL_STENCIL_TEST));
1450 GR_GL(StencilFunc(GL_ALWAYS, clipStencilMask, clipStencilMask));
1451 GR_GL(StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
1452 GR_GL(StencilMask(clipStencilMask));
1453 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1454 if (!fSingleStencilPassForWinding) {
1455 GR_GL(Disable(GL_CULL_FACE));
1456 }
1457 break;
1458 default:
1459 GrAssert(!"Unexpected stencil pass.");
1460 break;
1461
1462 }
1463 fHWDrawState.fStencilPass = fCurrDrawState.fStencilPass;
1464 fHWDrawState.fReverseFill = fCurrDrawState.fReverseFill;
1465 fWriteMaskChanged = false;
1466 fHWStencilClip = stencilClip;
1467 }
1468}
1469
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001470bool GrGpuGL::flushGLStateCommon(PrimitiveType type) {
1471
1472 // GrGpu::setupClipAndFlushState should have already checked this
1473 // and bailed if not true.
1474 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001475
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001476 for (int s = 0; s < kNumStages; ++s) {
1477 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001478
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001479 // bind texture and set sampler state
1480 if (usingTexture) {
1481 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001482
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001483 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001484 // if we created a rt/tex and rendered to it without using a
1485 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001486 // the last bound texture, but it needs resolving. So keep this
1487 // out of the "last != next" check.
1488 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001489
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001490 if (fHWDrawState.fTextures[s] != nextTexture) {
1491 setTextureUnit(s);
1492 GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
1493 #if GR_COLLECT_STATS
1494 ++fStats.fTextureChngCnt;
1495 #endif
1496 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1497 fHWDrawState.fTextures[s] = nextTexture;
1498 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001499
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001500 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001501 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001502 nextTexture->getTexParams();
1503 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001504
1505 newTexParams.fFilter = sampler.isFilter() ? GL_LINEAR :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001506 GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001507 newTexParams.fWrapS =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001508 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001509 newTexParams.fWrapT =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001510 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001511
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001512 if (newTexParams.fFilter != oldTexParams.fFilter) {
1513 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001514 GR_GL(TexParameteri(GL_TEXTURE_2D,
1515 GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001516 newTexParams.fFilter));
bsalomon@google.com316f99232011-01-13 21:28:12 +00001517 GR_GL(TexParameteri(GL_TEXTURE_2D,
1518 GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001519 newTexParams.fFilter));
1520 }
1521 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1522 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001523 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001524 GL_TEXTURE_WRAP_S,
1525 newTexParams.fWrapS));
1526 }
1527 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1528 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001529 GR_GL(TexParameteri(GL_TEXTURE_2D,
1530 GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001531 newTexParams.fWrapT));
1532 }
1533 nextTexture->setTexParams(newTexParams);
1534 } else {
1535 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001536 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001537 }
1538 }
1539 }
1540
1541 flushRenderTarget();
1542
1543 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1544 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1545 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
1546 GR_GL(Enable(GL_DITHER));
1547 } else {
1548 GR_GL(Disable(GL_DITHER));
1549 }
1550 }
1551
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001552#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +00001553 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1554 // smooth lines.
1555 if (fRenderTargetChanged ||
1556 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1557 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1558 GLint msaa = 0;
1559 // only perform query if we know MSAA is supported.
1560 // calling on non-MSAA target caused a crash in one environment,
1561 // though I don't think it should.
1562 if (!fAASamples[kHigh_AALevel]) {
reed@google.comac20fb92011-01-12 17:14:53 +00001563 GR_GL_GetIntegerv(GL_SAMPLE_BUFFERS, &msaa);
reed@google.comac10a2d2010-12-22 21:39:39 +00001564 }
1565 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1566 if (msaa) {
1567 GR_GL(Enable(GL_MULTISAMPLE));
1568 } else {
1569 GR_GL(Enable(GL_LINE_SMOOTH));
1570 }
1571 } else {
1572 if (msaa) {
1573 GR_GL(Disable(GL_MULTISAMPLE));
1574 }
1575 GR_GL(Disable(GL_LINE_SMOOTH));
1576 }
1577 }
1578#endif
1579
1580 bool blendOff = canDisableBlend();
1581 if (fHWBlendDisabled != blendOff) {
1582 if (blendOff) {
1583 GR_GL(Disable(GL_BLEND));
1584 } else {
1585 GR_GL(Enable(GL_BLEND));
1586 }
1587 fHWBlendDisabled = blendOff;
1588 }
1589
1590 if (!blendOff) {
1591 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1592 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1593 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1594 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1595 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1596 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1597 }
1598 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001599
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001600#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001601 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001602 for (int s = 0; s < kNumStages; ++s) {
1603 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1604 NULL == fCurrDrawState.fRenderTarget ||
1605 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001606 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001607 fCurrDrawState.fRenderTarget);
1608 }
1609#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001610
reed@google.comac10a2d2010-12-22 21:39:39 +00001611 flushStencil();
1612
1613 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001614 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001615}
1616
1617void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001618 if (fHWGeometryState.fVertexBuffer != buffer) {
1619 fHWGeometryState.fArrayPtrsDirty = true;
1620 fHWGeometryState.fVertexBuffer = buffer;
1621 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001622}
1623
1624void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1625 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1626 buffer == fGeometrySrc.fVertexBuffer));
1627
1628 if (fHWGeometryState.fVertexBuffer == buffer) {
1629 // deleting bound buffer does implied bind to 0
1630 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001631 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001632 }
1633}
1634
1635void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1636 fGeometrySrc.fIndexBuffer = buffer;
1637}
1638
1639void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1640 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1641 buffer == fGeometrySrc.fIndexBuffer));
1642
1643 if (fHWGeometryState.fIndexBuffer == buffer) {
1644 // deleting bound buffer does implied bind to 0
1645 fHWGeometryState.fIndexBuffer = NULL;
1646 }
1647}
1648
reed@google.comac10a2d2010-12-22 21:39:39 +00001649void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1650 GrAssert(NULL != renderTarget);
1651
1652 // if the bound FBO is destroyed we can't rely on the implicit bind to 0
1653 // a) we want the default RT which may not be FBO 0
1654 // b) we set more state than just FBO based on the RT
1655 // So trash the HW state to force an RT flush next time
1656 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001657 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001658 }
1659 if (fHWDrawState.fRenderTarget == renderTarget) {
1660 fHWDrawState.fRenderTarget = NULL;
1661 }
1662 if (fClipState.fStencilClipTarget == renderTarget) {
1663 fClipState.fStencilClipTarget = NULL;
1664 }
1665}
1666
1667void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001668 for (int s = 0; s < kNumStages; ++s) {
1669 if (fCurrDrawState.fTextures[s] == texture) {
1670 fCurrDrawState.fTextures[s] = NULL;
1671 }
1672 if (fHWDrawState.fTextures[s] == texture) {
1673 // deleting bound texture does implied bind to 0
1674 fHWDrawState.fTextures[s] = NULL;
1675 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001676 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001677}
1678
1679void GrGpuGL::notifyTextureRemoveRenderTarget(GrGLTexture* texture) {
1680 GrAssert(NULL != texture->asRenderTarget());
1681
1682 // if there is a pending resolve, perform it.
1683 resolveTextureRenderTarget(texture);
1684}
1685
1686bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
1687 GLenum* internalFormat,
1688 GLenum* format,
1689 GLenum* type) {
1690 switch (config) {
1691 case GrTexture::kRGBA_8888_PixelConfig:
1692 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001693 *format = GR_GL_32BPP_COLOR_FORMAT;
reed@google.com63100f92011-01-18 21:32:14 +00001694#if GR_SUPPORT_GLES
1695 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1696 // format for a BGRA is BGRA not RGBA (as on desktop)
1697 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1698#else
1699 *internalFormat = GL_RGBA;
bsalomon@google.comed3a0682011-01-18 16:54:04 +00001700#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001701 *type = GL_UNSIGNED_BYTE;
1702 break;
1703 case GrTexture::kRGB_565_PixelConfig:
1704 *format = GL_RGB;
1705 *internalFormat = GL_RGB;
1706 *type = GL_UNSIGNED_SHORT_5_6_5;
1707 break;
1708 case GrTexture::kRGBA_4444_PixelConfig:
1709 *format = GL_RGBA;
1710 *internalFormat = GL_RGBA;
1711 *type = GL_UNSIGNED_SHORT_4_4_4_4;
1712 break;
1713 case GrTexture::kIndex_8_PixelConfig:
1714 if (this->supports8BitPalette()) {
1715 *format = GR_PALETTE8_RGBA8;
1716 *internalFormat = GR_PALETTE8_RGBA8;
1717 *type = GL_UNSIGNED_BYTE; // unused I think
1718 } else {
1719 return false;
1720 }
1721 break;
1722 case GrTexture::kAlpha_8_PixelConfig:
1723 *format = GL_ALPHA;
1724 *internalFormat = GL_ALPHA;
1725 *type = GL_UNSIGNED_BYTE;
1726 break;
1727 default:
1728 return false;
1729 }
1730 return true;
1731}
1732
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001733void GrGpuGL::setTextureUnit(int unit) {
1734 GrAssert(unit >= 0 && unit < kNumStages);
1735 if (fActiveTextureUnitIdx != unit) {
1736 GR_GL(ActiveTexture(GL_TEXTURE0 + unit));
1737 fActiveTextureUnitIdx = unit;
1738 }
1739}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001740
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001741void GrGpuGL::setSpareTextureUnit() {
1742 if (fActiveTextureUnitIdx != (GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1743 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
1744 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1745 }
1746}
1747
reed@google.comac10a2d2010-12-22 21:39:39 +00001748/* On ES the internalFormat and format must match for TexImage and we use
1749 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1750 decide the internalFormat. However, on ES internalFormat for
1751 RenderBufferStorage* has to be a specific format (not a base format like
1752 GL_RGBA).
1753 */
1754bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) {
1755 switch (config) {
1756 case GrTexture::kRGBA_8888_PixelConfig:
1757 case GrTexture::kRGBX_8888_PixelConfig:
1758 if (fRGBA8Renderbuffer) {
1759 *format = GR_RGBA8;
1760 return true;
1761 } else {
1762 return false;
1763 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001764#if GR_SUPPORT_GLES // ES2 supports 565. ES1 supports it with FBO extension
1765 // desktop GL has no such internal format
reed@google.comac10a2d2010-12-22 21:39:39 +00001766 case GrTexture::kRGB_565_PixelConfig:
1767 *format = GR_RGB565;
1768 return true;
1769#endif
1770 case GrTexture::kRGBA_4444_PixelConfig:
1771 *format = GL_RGBA4;
1772 return true;
1773 default:
1774 return false;
1775 }
1776}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001777
1778
1779const GLvoid* GrGpuGL::setBuffersAndGetVertexStart(int vertexStride, int startVertex,
1780 int startIndex, int vertexCount,
1781 int indexCount) {
1782 const GLvoid* posPtr = (GLvoid*)(vertexStride * startVertex);
1783
1784 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
1785 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
1786 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
1787 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
1788 GrGLVertexBuffer* buf =
1789 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
1790 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
1791 fHWGeometryState.fArrayPtrsDirty = true;
1792 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
1793 }
1794 } else {
1795 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
1796 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
1797 (intptr_t)posPtr);
1798 } else {
1799 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
1800 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
1801 }
1802 #if GR_GL_NO_CLIENT_SIDE_ARRAYS
1803 putClientVertexDataInBuffer(posPtr, vertexCount * vertexStride);
1804 posPtr = NULL;
1805 if (fHWGeometryState.fVertexBuffer != fClientArrayVB) {
1806 GR_GL(BindBuffer(GL_ARRAY_BUFFER, fClientArrayVB->bufferID()));
1807 fHWGeometryState.fArrayPtrsDirty = true;
1808 fHWGeometryState.fVertexBuffer = fClientArrayVB;
1809 }
1810 #else
1811 if (NULL != fHWGeometryState.fVertexBuffer) {
1812 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
1813 fHWGeometryState.fArrayPtrsDirty = true;
1814 fHWGeometryState.fVertexBuffer = NULL;
1815 }
1816 #endif
1817 }
1818
1819 if (0 != indexCount) {
1820
1821 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1822 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
1823 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
1824 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
1825 GrGLIndexBuffer* buf =
1826 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1827 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
1828 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
1829 }
1830 }
1831 #if GR_GL_NO_CLIENT_SIDE_ARRAYS
1832 else {
1833 const uint16_t* indices;
1834 if (kArray_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1835 indices = reinterpret_cast<const uint16_t*>(fGeometrySrc.fIndexArray);
1836 } else {
1837 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fIndexSrc);
1838 indices = reinterpret_cast<const uint16_t*>(fIndices.get());
1839 }
1840 // we shove just the referenced part of the index data into the begining
1841 // of the buffer and drawIndexedHelper ignores startIndex.
1842 putClientIndexDataInBuffer(indices + startIndex, indexCount * sizeof(uint16_t));
1843 if (fHWGeometryState.fIndexBuffer != fClientArrayIB) {
1844 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, fClientArrayIB->bufferID()));
1845 fHWGeometryState.fIndexBuffer = fClientArrayIB;
1846 }
1847 }
1848 #else
1849 else if (NULL != fHWGeometryState.fIndexBuffer) {
1850 // we rely on drawIndexedHelper to pass to client side
1851 // ptr to DrawElements
1852 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
1853 fHWGeometryState.fIndexBuffer = NULL;
1854 }
1855 #endif
1856 }
1857 return posPtr;
1858}