blob: 0b5927a3cc71a986d97b5d4a9261ae0182016575 [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;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000469 }
470 fClientArrayVB->updateData(vertexData, vertexDataSize);
471 if (currMinVBSize == MIN_VB_SIZE && fClientArrayVB->size() > MIN_VB_SIZE) {
472 ++fOversizeVBDrawCnt;
473 }
474 }
475}
476
477void GrGpuGL::putClientIndexDataInBuffer(const void* indexData, size_t indexDataSize) {
478 static const size_t MIN_IB_SIZE = 1 << 8;
479 static const int MAX_OVERSIZE_IB_DRAWS = 100;
480
481 if (NULL != indexData) {
482 size_t currMinIBSize = GrMax(MIN_IB_SIZE, indexDataSize);
483 // if we don't have a IB, its too small, or too big, create a new one
484 if (NULL == fClientArrayIB ||
485 fClientArrayIB->size() < currMinIBSize ||
486 (fOversizeIBDrawCnt >= MAX_OVERSIZE_IB_DRAWS &&
487 currMinIBSize == MIN_IB_SIZE &&
488 fClientArrayIB->size() > MIN_IB_SIZE)) {
489
490 if (fHWGeometryState.fIndexBuffer == fClientArrayIB) {
491 fHWGeometryState.fIndexBuffer = NULL;
492 }
493 GrSafeUnref(fClientArrayIB);
494 fClientArrayIB = (GrGLIndexBuffer*)createIndexBuffer(currMinIBSize, true);
495 fOversizeIBDrawCnt = 0;
496 }
497 fClientArrayIB->updateData(indexData, indexDataSize);
498 if (currMinIBSize == MIN_IB_SIZE && fClientArrayIB->size() > MIN_IB_SIZE) {
499 ++fOversizeIBDrawCnt;
500 }
501 }
502}
503#endif
504
reed@google.comac10a2d2010-12-22 21:39:39 +0000505GrRenderTarget* GrGpuGL::createPlatformRenderTarget(
506 intptr_t platformRenderTarget,
507 int width, int height) {
508 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
509 rtIDs.fStencilRenderbufferID = 0;
510 rtIDs.fMSColorRenderbufferID = 0;
511 rtIDs.fTexFBOID = 0;
512 rtIDs.fOwnIDs = false;
513
514 GrIRect viewport;
515
516 // viewport is in GL coords (top >= bottom)
517 viewport.setLTRB(0, height, width, 0);
518
519 rtIDs.fRTFBOID = (GLuint)platformRenderTarget;
520 rtIDs.fTexFBOID = (GLuint)platformRenderTarget;
521
522 GrGLRenderTarget* rt = new GrGLRenderTarget(rtIDs, viewport, NULL, this);
523
524 return rt;
525}
526
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000527GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000528
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000529 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000530
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000531 GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&rtIDs.fRTFBOID);
532 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
533 rtIDs.fMSColorRenderbufferID = 0;
534 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000535
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000536 GLint vp[4];
537 GR_GL_GetIntegerv(GL_VIEWPORT, vp);
538 GrIRect viewportRect;
539 viewportRect.setLTRB(vp[0],
540 vp[1] + vp[3],
541 vp[0] + vp[2],
542 vp[1]);
543 rtIDs.fOwnIDs = false;
544
545 return new GrGLRenderTarget(rtIDs,
546 viewportRect,
547 NULL,
548 this);
549}
550
bsalomon@google.com5782d712011-01-21 21:03:59 +0000551///////////////////////////////////////////////////////////////////////////////
552
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000553// defines stencil formats from more to less preferred
reed@google.com63100f92011-01-18 21:32:14 +0000554GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = {
555 GR_STENCIL_INDEX8,
556
557#if GR_SUPPORT_GLDESKTOP
558 GR_STENCIL_INDEX16,
559#endif
560
561 GR_DEPTH24_STENCIL8,
562 GR_STENCIL_INDEX4,
563
564#if GR_SUPPORT_GLDESKTOP
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000565 GL_STENCIL_INDEX,
566 GR_DEPTH_STENCIL,
567#endif
568};
569
570// good to set a break-point here to know when createTexture fails
571static GrTexture* return_null_texture() {
572// GrAssert(!"null texture");
573 return NULL;
574}
575
576#if GR_DEBUG
577static size_t as_size_t(int x) {
578 return x;
579}
580#endif
581
reed@google.comac10a2d2010-12-22 21:39:39 +0000582GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
583 const void* srcData, size_t rowBytes) {
584
585#if GR_COLLECT_STATS
586 ++fStats.fTextureCreateCnt;
587#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000588
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000589 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000590
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000591 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
592 GL_NEAREST,
593 GL_CLAMP_TO_EDGE,
594 GL_CLAMP_TO_EDGE
595 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000596
reed@google.comac10a2d2010-12-22 21:39:39 +0000597 GrGLTexture::GLTextureDesc glDesc;
598 GLenum internalFormat;
599
600 glDesc.fContentWidth = desc.fWidth;
601 glDesc.fContentHeight = desc.fHeight;
602 glDesc.fAllocWidth = desc.fWidth;
603 glDesc.fAllocHeight = desc.fHeight;
604 glDesc.fFormat = desc.fFormat;
605
606 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
607 if (!canBeTexture(desc.fFormat,
608 &internalFormat,
609 &glDesc.fUploadFormat,
610 &glDesc.fUploadType)) {
611 return return_null_texture();
612 }
613
614 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
615 GLint samples = fAASamples[desc.fAALevel];
616 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
617 GrPrintf("AA RT requested but not supported on this platform.");
618 }
619
620 GR_GL(GenTextures(1, &glDesc.fTextureID));
621 if (!glDesc.fTextureID) {
622 return return_null_texture();
623 }
624
625 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
626
627 /*
628 * check if our srcData has extra bytes past each row. If so, we need
629 * to trim those off here, since GL doesn't let us pass the rowBytes as
630 * a parameter to glTexImage2D
631 */
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000632#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000633 if (srcData) {
634 GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH,
635 rowBytes / glDesc.fUploadByteCount));
636 }
637#else
638 GrAutoSMalloc<128 * 128> trimStorage;
639 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
640 if (srcData && (trimRowBytes < rowBytes)) {
641 size_t trimSize = desc.fHeight * trimRowBytes;
642 trimStorage.realloc(trimSize);
643 // now copy the data into our new storage, skipping the trailing bytes
644 const char* src = (const char*)srcData;
645 char* dst = (char*)trimStorage.get();
646 for (uint32_t y = 0; y < desc.fHeight; y++) {
647 memcpy(dst, src, trimRowBytes);
648 src += rowBytes;
649 dst += trimRowBytes;
650 }
651 // now point srcData to our trimmed version
652 srcData = trimStorage.get();
653 }
654#endif
655
reed@google.comac10a2d2010-12-22 21:39:39 +0000656 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000657 if (!this->npotRenderTargetSupport()) {
658 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
659 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
660 }
661
reed@google.comac10a2d2010-12-22 21:39:39 +0000662 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
663 glDesc.fAllocWidth);
664 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
665 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000666 } else if (!this->npotTextureSupport()) {
667 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
668 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000669 }
670
671 GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000672 GR_GL(TexParameteri(GL_TEXTURE_2D,
673 GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000674 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000675 GR_GL(TexParameteri(GL_TEXTURE_2D,
676 GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000677 DEFAULT_PARAMS.fFilter));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000678 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000679 GL_TEXTURE_WRAP_S,
680 DEFAULT_PARAMS.fWrapS));
reed@google.com1fcd51e2011-01-05 15:50:27 +0000681 GR_GL(TexParameteri(GL_TEXTURE_2D,
682 GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000683 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000684
685 GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
686 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
687 supports8BitPalette()) {
688 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
689 GrAssert(desc.fWidth == glDesc.fAllocWidth);
690 GrAssert(desc.fHeight == glDesc.fAllocHeight);
691 GLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
692 kColorTableSize;
693 GR_GL(CompressedTexImage2D(GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
694 glDesc.fAllocWidth, glDesc.fAllocHeight,
695 0, imageSize, srcData));
696 GrGL_RestoreResetRowLength();
697 } else {
698 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
699 glDesc.fAllocHeight != desc.fHeight)) {
700 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat,
701 glDesc.fAllocWidth, glDesc.fAllocHeight,
702 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
703 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
704 desc.fHeight, glDesc.fUploadFormat,
705 glDesc.fUploadType, srcData));
706 GrGL_RestoreResetRowLength();
707
708 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
709 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
710 uint32_t maxTexels = extraW * extraH;
711 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
712 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
713
714 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
715
716 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
717 if (extraH) {
718 uint8_t* lastRowStart = (uint8_t*) srcData +
719 (desc.fHeight - 1) * rowSize;
720 uint8_t* extraRowStart = (uint8_t*)texels.get();
721
722 for (uint32_t i = 0; i < extraH; ++i) {
723 memcpy(extraRowStart, lastRowStart, rowSize);
724 extraRowStart += rowSize;
725 }
726 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
727 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
728 texels.get()));
729 }
730 if (extraW) {
731 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
732 uint8_t* extraTexel = (uint8_t*)texels.get();
733 for (uint32_t j = 0; j < desc.fHeight; ++j) {
734 for (uint32_t i = 0; i < extraW; ++i) {
735 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
736 extraTexel += glDesc.fUploadByteCount;
737 }
738 edgeTexel += rowSize;
739 }
740 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
741 desc.fHeight, glDesc.fUploadFormat,
742 glDesc.fUploadType, texels.get()));
743 }
744 if (extraW && extraH) {
745 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
746 - glDesc.fUploadByteCount;
747 uint8_t* extraTexel = (uint8_t*)texels.get();
748 for (uint32_t i = 0; i < extraW*extraH; ++i) {
749 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
750 extraTexel += glDesc.fUploadByteCount;
751 }
752 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
753 extraW, extraH, glDesc.fUploadFormat,
754 glDesc.fUploadType, texels.get()));
755 }
756
757 } else {
758 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
759 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
760 glDesc.fUploadType, srcData));
761 GrGL_RestoreResetRowLength();
762 }
763 }
764
765 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
766
767 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
768 rtIDs.fStencilRenderbufferID = 0;
769 rtIDs.fMSColorRenderbufferID = 0;
770 rtIDs.fRTFBOID = 0;
771 rtIDs.fTexFBOID = 0;
772 rtIDs.fOwnIDs = true;
773 GLenum msColorRenderbufferFormat = -1;
774
775 if (renderTarget) {
776#if GR_COLLECT_STATS
777 ++fStats.fRenderTargetCreateCnt;
778#endif
779 bool failed = true;
780 GLenum status;
781 GLint err;
782
783 // If need have both RT flag and srcData we have
784 // to invert the data before uploading because FBO
785 // will be rendered bottom up
786 GrAssert(NULL == srcData);
787 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
788
789 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fTexFBOID));
790 GrAssert(rtIDs.fTexFBOID);
791
792 // If we are using multisampling and any extension other than the IMG
793 // one we will create two FBOs. We render to one and then resolve to
794 // the texture bound to the other. The IMG extension does an implicit
795 // resolve.
796 if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
797 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fRTFBOID));
798 GrAssert(0 != rtIDs.fRTFBOID);
799 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
800 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
801 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
802 GR_GLEXT(fExts,
803 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
804 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
805 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
806 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000807 return return_null_texture();
808 }
809 } else {
810 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
811 }
812 int attempts = 1;
813 if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
814 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
815 GrAssert(0 != rtIDs.fStencilRenderbufferID);
816 attempts = GR_ARRAY_COUNT(GR_GL_STENCIL_FORMAT_ARRAY);
817 }
818
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000819 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000820 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000821 // (seems unlikely)
reed@google.comac10a2d2010-12-22 21:39:39 +0000822 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000823
824 err = ~GL_NO_ERROR;
825 for (int i = 0; i < attempts; ++i) {
826 if (rtIDs.fStencilRenderbufferID) {
827 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
828 rtIDs.fStencilRenderbufferID));
829 if (samples > 1) {
830 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
831 GR_RENDERBUFFER,
832 samples,
833 GR_GL_STENCIL_FORMAT_ARRAY[i],
834 glDesc.fAllocWidth,
835 glDesc.fAllocHeight));
836 } else {
837 GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
838 GR_RENDERBUFFER,
839 GR_GL_STENCIL_FORMAT_ARRAY[i],
840 glDesc.fAllocWidth,
841 glDesc.fAllocHeight));
842 }
843 err = glGetError();
844 if (err != GL_NO_ERROR) {
845 continue;
846 }
847 }
848 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
849 GrAssert(samples > 1);
850 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
851 rtIDs.fMSColorRenderbufferID));
852 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
853 GR_RENDERBUFFER,
854 samples,
855 msColorRenderbufferFormat,
856 glDesc.fAllocWidth,
857 glDesc.fAllocHeight));
858 err = glGetError();
859 if (err != GL_NO_ERROR) {
860 continue;
861 }
862 }
863 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
864
865#if GR_COLLECT_STATS
866 ++fStats.fRenderTargetChngCnt;
867#endif
868 if (kIMG_MSFBO == fMSFBOType && samples > 1) {
869 GR_GLEXT(fExts, FramebufferTexture2DMultisample(
870 GR_FRAMEBUFFER,
871 GR_COLOR_ATTACHMENT0,
872 GL_TEXTURE_2D,
873 glDesc.fTextureID,
874 0,
875 samples));
876
877 } else {
878 GR_GLEXT(fExts, FramebufferTexture2D(GR_FRAMEBUFFER,
879 GR_COLOR_ATTACHMENT0,
880 GL_TEXTURE_2D,
881 glDesc.fTextureID, 0));
882 }
883 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
884 GLenum status = GR_GLEXT(fExts,
885 CheckFramebufferStatus(GR_FRAMEBUFFER));
886 if (status != GR_FRAMEBUFFER_COMPLETE) {
887 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
888 status, desc.fWidth, desc.fHeight);
889 continue;
890 }
891 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
892 #if GR_COLLECT_STATS
893 ++fStats.fRenderTargetChngCnt;
894 #endif
895 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
896 GR_COLOR_ATTACHMENT0,
897 GR_RENDERBUFFER,
898 rtIDs.fMSColorRenderbufferID));
899
900 }
901 if (rtIDs.fStencilRenderbufferID) {
902 // bind the stencil to rt fbo if present, othewise the tex fbo
903 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
904 GR_STENCIL_ATTACHMENT,
bsalomon@google.com5782d712011-01-21 21:03:59 +0000905 GR_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000906 rtIDs.fStencilRenderbufferID));
907 }
908 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
909
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000910#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000911 // On some implementations you have to be bound as DEPTH_STENCIL.
912 // (Even binding to DEPTH and STENCIL separately with the same
913 // buffer doesn't work.)
914 if (rtIDs.fStencilRenderbufferID &&
915 status != GR_FRAMEBUFFER_COMPLETE) {
916 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
917 GR_STENCIL_ATTACHMENT,
918 GR_RENDERBUFFER,
919 0));
920 GR_GLEXT(fExts,
921 FramebufferRenderbuffer(GR_FRAMEBUFFER,
922 GR_DEPTH_STENCIL_ATTACHMENT,
923 GR_RENDERBUFFER,
924 rtIDs.fStencilRenderbufferID));
925 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
926 }
927#endif
928 if (status != GR_FRAMEBUFFER_COMPLETE) {
929 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
930 status, desc.fWidth, desc.fHeight);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000931#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +0000932 if (rtIDs.fStencilRenderbufferID) {
933 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
934 GR_DEPTH_STENCIL_ATTACHMENT,
935 GR_RENDERBUFFER,
936 0));
937 }
938#endif
939 continue;
940 }
941 // we're successful!
942 failed = false;
943 break;
944 }
945 if (failed) {
946 if (rtIDs.fStencilRenderbufferID) {
947 GR_GLEXT(fExts,
948 DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
949 }
950 if (rtIDs.fMSColorRenderbufferID) {
951 GR_GLEXT(fExts,
952 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
953 }
954 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
955 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
956 }
957 if (rtIDs.fTexFBOID) {
958 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
959 }
960 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
961 return return_null_texture();
962 }
963 }
964#ifdef TRACE_TEXTURE_CREATION
965 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
966 tex->fTextureID, width, height, tex->fUploadByteCount);
967#endif
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000968 GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, DEFAULT_PARAMS, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000969
970 if (0 != rtIDs.fTexFBOID) {
971 GrRenderTarget* rt = tex->asRenderTarget();
972 // We've messed with FBO state but may not have set the correct viewport
973 // so just dirty the rendertarget state to force a resend.
974 fHWDrawState.fRenderTarget = NULL;
975
976 // clear the new stencil buffer if we have one
977 if (!(desc.fFlags & kNoPathRendering_TextureFlag)) {
978 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
979 fCurrDrawState.fRenderTarget = rt;
980 eraseStencil(0, ~0);
981 fCurrDrawState.fRenderTarget = rtSave;
982 }
983 }
984 return tex;
985}
986
reed@google.comac10a2d2010-12-22 21:39:39 +0000987GrVertexBuffer* GrGpuGL::createVertexBuffer(uint32_t size, bool dynamic) {
988 GLuint id;
989 GR_GL(GenBuffers(1, &id));
990 if (id) {
991 GR_GL(BindBuffer(GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000992 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000993 GrGLClearErr();
994 // make sure driver can allocate memory for this buffer
995 GR_GL_NO_ERR(BufferData(GL_ARRAY_BUFFER, size, NULL,
996 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
997 if (glGetError() != GL_NO_ERROR) {
998 GR_GL(DeleteBuffers(1, &id));
999 // deleting bound buffer does implicit bind to 0
1000 fHWGeometryState.fVertexBuffer = NULL;
1001 return NULL;
1002 }
1003 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this,
1004 size, dynamic);
1005 fHWGeometryState.fVertexBuffer = vertexBuffer;
1006 return vertexBuffer;
1007 }
1008 return NULL;
1009}
1010
1011GrIndexBuffer* GrGpuGL::createIndexBuffer(uint32_t size, bool dynamic) {
1012 GLuint id;
1013 GR_GL(GenBuffers(1, &id));
1014 if (id) {
1015 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, id));
1016 GrGLClearErr();
1017 // make sure driver can allocate memory for this buffer
1018 GR_GL_NO_ERR(BufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1019 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
1020 if (glGetError() != GL_NO_ERROR) {
1021 GR_GL(DeleteBuffers(1, &id));
1022 // deleting bound buffer does implicit bind to 0
1023 fHWGeometryState.fIndexBuffer = NULL;
1024 return NULL;
1025 }
1026 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this,
1027 size, dynamic);
1028 fHWGeometryState.fIndexBuffer = indexBuffer;
1029 return indexBuffer;
1030 }
1031 return NULL;
1032}
1033
reed@google.comac10a2d2010-12-22 21:39:39 +00001034void GrGpuGL::flushScissor(const GrIRect* rect) {
1035 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1036 const GrIRect& vp =
1037 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1038
1039 if (NULL != rect &&
1040 rect->contains(vp)) {
1041 rect = NULL;
1042 }
1043
1044 if (NULL != rect) {
1045 GrIRect scissor;
1046 // viewport is already in GL coords
1047 // create a scissor in GL coords (top > bottom)
1048 scissor.setLTRB(vp.fLeft + rect->fLeft,
1049 vp.fTop - rect->fTop,
1050 vp.fLeft + rect->fRight,
1051 vp.fTop - rect->fBottom);
1052
1053 if (fHWBounds.fScissorRect != scissor) {
1054 GR_GL(Scissor(scissor.fLeft, scissor.fBottom,
1055 scissor.width(), -scissor.height()));
1056 fHWBounds.fScissorRect = scissor;
1057 }
1058
1059 if (!fHWBounds.fScissorEnabled) {
1060 GR_GL(Enable(GL_SCISSOR_TEST));
1061 fHWBounds.fScissorEnabled = true;
1062 }
1063 } else {
1064 if (fHWBounds.fScissorEnabled) {
1065 GR_GL(Disable(GL_SCISSOR_TEST));
1066 fHWBounds.fScissorEnabled = false;
1067 }
1068 }
1069}
1070
reed@google.comac10a2d2010-12-22 21:39:39 +00001071void GrGpuGL::eraseColor(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001072 if (NULL == fCurrDrawState.fRenderTarget) {
1073 return;
1074 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001075 flushRenderTarget();
1076 if (fHWBounds.fScissorEnabled) {
1077 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001078 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001079 }
1080 GR_GL(ColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE));
1081 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1082 GrColorUnpackG(color)/255.f,
1083 GrColorUnpackB(color)/255.f,
1084 GrColorUnpackA(color)/255.f));
1085 GR_GL(Clear(GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001086 fWriteMaskChanged = true;
1087}
1088
1089void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001090 if (NULL == fCurrDrawState.fRenderTarget) {
1091 return;
1092 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001093 flushRenderTarget();
1094 if (fHWBounds.fScissorEnabled) {
1095 GR_GL(Disable(GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001096 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 }
1098 GR_GL(StencilMask(mask));
1099 GR_GL(ClearStencil(value));
1100 GR_GL(Clear(GL_STENCIL_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001101 fWriteMaskChanged = true;
1102}
1103
1104void GrGpuGL::eraseStencilClip() {
1105 GLint stencilBitCount;
reed@google.comac20fb92011-01-12 17:14:53 +00001106 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001107 GrAssert(stencilBitCount > 0);
1108 GLint clipStencilMask = (1 << (stencilBitCount - 1));
1109 eraseStencil(0, clipStencilMask);
1110}
1111
1112void GrGpuGL::forceRenderTargetFlush() {
1113 flushRenderTarget();
1114}
1115
1116bool GrGpuGL::readPixels(int left, int top, int width, int height,
1117 GrTexture::PixelConfig config, void* buffer) {
1118 GLenum internalFormat; // we don't use this for glReadPixels
1119 GLenum format;
1120 GLenum type;
1121 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1122 return false;
1123 }
1124
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001125 if (NULL == fCurrDrawState.fRenderTarget) {
1126 return false;
1127 }
1128 flushRenderTarget();
1129
reed@google.comac10a2d2010-12-22 21:39:39 +00001130 const GrIRect& vp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1131
1132 // Brian says that viewport rects are already upside down (grrrrr)
bsalomon@google.com316f99232011-01-13 21:28:12 +00001133 GR_GL(ReadPixels(left, -vp.height() - top - height, width, height,
1134 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001135
1136 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1137 // API presents top-to-bottom
1138 {
1139 size_t stride = width * GrTexture::BytesPerPixel(config);
1140 GrAutoMalloc rowStorage(stride);
1141 void* tmp = rowStorage.get();
1142
1143 const int halfY = height >> 1;
1144 char* top = reinterpret_cast<char*>(buffer);
1145 char* bottom = top + (height - 1) * stride;
1146 for (int y = 0; y < halfY; y++) {
1147 memcpy(tmp, top, stride);
1148 memcpy(top, bottom, stride);
1149 memcpy(bottom, tmp, stride);
1150 top += stride;
1151 bottom -= stride;
1152 }
1153 }
1154 return true;
1155}
1156
1157void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001158
1159 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1160
reed@google.comac10a2d2010-12-22 21:39:39 +00001161 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1162 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
1163 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
1164 #if GR_COLLECT_STATS
1165 ++fStats.fRenderTargetChngCnt;
1166 #endif
1167 rt->setDirty(true);
1168 #if GR_DEBUG
1169 GLenum status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
1170 if (status != GR_FRAMEBUFFER_COMPLETE) {
1171 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1172 }
1173 #endif
1174 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
1175 const GrIRect& vp = rt->viewport();
1176 fRenderTargetChanged = true;
1177 if (fHWBounds.fViewportRect != vp) {
1178 GR_GL(Viewport(vp.fLeft,
1179 vp.fBottom,
1180 vp.width(),
1181 -vp.height()));
1182 fHWBounds.fViewportRect = vp;
1183 }
1184 }
1185}
1186
1187GLenum gPrimitiveType2GLMode[] = {
1188 GL_TRIANGLES,
1189 GL_TRIANGLE_STRIP,
1190 GL_TRIANGLE_FAN,
1191 GL_POINTS,
1192 GL_LINES,
1193 GL_LINE_STRIP
1194};
1195
1196void GrGpuGL::drawIndexedHelper(PrimitiveType type,
1197 uint32_t startVertex,
1198 uint32_t startIndex,
1199 uint32_t vertexCount,
1200 uint32_t indexCount) {
1201 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1202
1203 GLvoid* indices = (GLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001204
1205#if GR_GL_NO_CLIENT_SIDE_ARRAYS
1206 if (kBuffer_GeometrySrcType != fGeometrySrc.fIndexSrc) {
1207 // we accounted for the startIndex when shoving data into a vb
1208 indices = NULL;
1209 }
1210#else
reed@google.comac10a2d2010-12-22 21:39:39 +00001211 if (kReserved_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1212 indices = (GLvoid*)((intptr_t)indices + (intptr_t)fIndices.get());
1213 } else if (kArray_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1214 indices = (GLvoid*)((intptr_t)indices +
1215 (intptr_t)fGeometrySrc.fIndexArray);
1216 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001217#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001218
1219 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1220 GL_UNSIGNED_SHORT, indices));
1221}
1222
1223void GrGpuGL::drawNonIndexedHelper(PrimitiveType type,
1224 uint32_t startVertex,
1225 uint32_t vertexCount) {
1226 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1227
1228 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1229}
1230
reed@google.comac10a2d2010-12-22 21:39:39 +00001231void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1232 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1233
1234 if (NULL != rt && rt->needsResolve()) {
1235 GrAssert(kNone_MSFBO != fMSFBOType);
1236 GrAssert(rt->textureFBOID() != rt->renderFBOID());
1237 GR_GLEXT(fExts, BindFramebuffer(GR_READ_FRAMEBUFFER,
1238 rt->renderFBOID()));
1239 GR_GLEXT(fExts, BindFramebuffer(GR_DRAW_FRAMEBUFFER,
1240 rt->textureFBOID()));
1241 #if GR_COLLECT_STATS
1242 ++fStats.fRenderTargetChngCnt;
1243 #endif
1244 // make sure we go through set render target
1245 fHWDrawState.fRenderTarget = NULL;
1246
1247 GLint left = 0;
1248 GLint right = texture->contentWidth();
1249 // we will have rendered to the top of the FBO.
1250 GLint top = texture->allocHeight();
1251 GLint bottom = texture->allocHeight() - texture->contentHeight();
1252 if (kApple_MSFBO == fMSFBOType) {
1253 GR_GL(Enable(GL_SCISSOR_TEST));
1254 GR_GL(Scissor(left, bottom, right-left, top-bottom));
1255 GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
1256 fHWBounds.fScissorRect.setEmpty();
1257 fHWBounds.fScissorEnabled = true;
1258 } else {
1259 GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
1260 left, bottom, right, top,
1261 GL_COLOR_BUFFER_BIT, GL_NEAREST));
1262 }
1263 rt->setDirty(false);
1264
1265 }
1266}
1267
1268void GrGpuGL::flushStencil() {
1269
1270 // use stencil for clipping if clipping is enabled and the clip
1271 // has been written into the stencil.
1272 bool stencilClip = fClipState.fClipInStencil &&
1273 (kClip_StateBit & fCurrDrawState.fFlagBits);
1274 bool stencilChange =
1275 fWriteMaskChanged ||
1276 fHWStencilClip != stencilClip ||
1277 fHWDrawState.fStencilPass != fCurrDrawState.fStencilPass ||
1278 (kNone_StencilPass != fCurrDrawState.fStencilPass &&
1279 (StencilPass)kSetClip_StencilPass != fCurrDrawState.fStencilPass &&
1280 fHWDrawState.fReverseFill != fCurrDrawState.fReverseFill);
1281
1282 if (stencilChange) {
1283 GLint stencilBitCount;
1284 GLint clipStencilMask;
1285 GLint pathStencilMask;
reed@google.comac20fb92011-01-12 17:14:53 +00001286 GR_GL_GetIntegerv(GL_STENCIL_BITS, &stencilBitCount);
reed@google.comac10a2d2010-12-22 21:39:39 +00001287 GrAssert(stencilBitCount > 0 ||
1288 kNone_StencilPass == fCurrDrawState.fStencilPass);
1289 clipStencilMask = (1 << (stencilBitCount - 1));
1290 pathStencilMask = clipStencilMask - 1;
1291 switch (fCurrDrawState.fStencilPass) {
1292 case kNone_StencilPass:
1293 if (stencilClip) {
1294 GR_GL(Enable(GL_STENCIL_TEST));
1295 GR_GL(StencilFunc(GL_EQUAL,
1296 clipStencilMask,
1297 clipStencilMask));
1298 GR_GL(StencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
1299 } else {
1300 GR_GL(Disable(GL_STENCIL_TEST));
1301 }
1302 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1303 if (!fSingleStencilPassForWinding) {
1304 GR_GL(Disable(GL_CULL_FACE));
1305 }
1306 break;
1307 case kEvenOddStencil_StencilPass:
1308 GR_GL(Enable(GL_STENCIL_TEST));
1309 if (stencilClip) {
1310 GR_GL(StencilFunc(GL_EQUAL, clipStencilMask, clipStencilMask));
1311 } else {
1312 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1313 }
1314 GR_GL(StencilMask(pathStencilMask));
1315 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1316 GR_GL(StencilOp(GL_KEEP, GL_INVERT, GL_INVERT));
1317 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1318 if (!fSingleStencilPassForWinding) {
1319 GR_GL(Disable(GL_CULL_FACE));
1320 }
1321 break;
1322 case kEvenOddColor_StencilPass: {
1323 GR_GL(Enable(GL_STENCIL_TEST));
1324 GLint funcRef = 0;
1325 GLuint funcMask = pathStencilMask;
1326 if (stencilClip) {
1327 funcRef |= clipStencilMask;
1328 funcMask |= clipStencilMask;
1329 }
1330 if (!fCurrDrawState.fReverseFill) {
1331 funcRef |= pathStencilMask;
1332 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001333 GR_GL(StencilFunc(GL_EQUAL, funcRef, funcMask));
1334 GR_GL(StencilMask(pathStencilMask));
reed@google.comac10a2d2010-12-22 21:39:39 +00001335 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1336 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1337 if (!fSingleStencilPassForWinding) {
1338 GR_GL(Disable(GL_CULL_FACE));
1339 }
1340 } break;
1341 case kWindingStencil1_StencilPass:
1342 GR_GL(Enable(GL_STENCIL_TEST));
1343 if (fHasStencilWrap) {
1344 if (stencilClip) {
1345 GR_GL(StencilFunc(GL_EQUAL,
1346 clipStencilMask,
1347 clipStencilMask));
1348 } else {
1349 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1350 }
1351 if (fSingleStencilPassForWinding) {
1352 GR_GL(StencilOpSeparate(GL_FRONT, GL_KEEP,
1353 GL_INCR_WRAP, GL_INCR_WRAP));
1354 GR_GL(StencilOpSeparate(GL_BACK, GL_KEEP,
1355 GL_DECR_WRAP, GL_DECR_WRAP));
1356 } else {
1357 GR_GL(StencilOp(GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP));
1358 GR_GL(Enable(GL_CULL_FACE));
1359 GR_GL(CullFace(GL_BACK));
1360 }
1361 } else {
1362 // If we don't have wrap then we use the Func to detect
1363 // values that would wrap (0 on decr and mask on incr). We
1364 // make the func fail on these values and use the sfail op
1365 // to effectively wrap by inverting.
1366 // This applies whether we are doing a two-pass (front faces
1367 // followed by back faces) or a single pass (separate func/op)
1368
1369 // Note that in the case where we are also using stencil to
1370 // clip this means we will write into the path bits in clipped
1371 // out pixels. We still apply the clip bit in the color pass
1372 // stencil func so we don't draw color outside the clip.
1373 // We also will clear the stencil bits in clipped pixels by
1374 // using zero in the sfail op with write mask set to the
1375 // path mask.
1376 GR_GL(Enable(GL_STENCIL_TEST));
1377 if (fSingleStencilPassForWinding) {
1378 GR_GL(StencilFuncSeparate(GL_FRONT,
1379 GL_NOTEQUAL,
1380 pathStencilMask,
1381 pathStencilMask));
1382 GR_GL(StencilFuncSeparate(GL_BACK,
1383 GL_NOTEQUAL,
1384 0x0,
1385 pathStencilMask));
1386 GR_GL(StencilOpSeparate(GL_FRONT, GL_INVERT,
1387 GL_INCR, GL_INCR));
1388 GR_GL(StencilOpSeparate(GL_BACK, GL_INVERT,
1389 GL_DECR, GL_DECR));
1390 } else {
1391 GR_GL(StencilFunc(GL_NOTEQUAL,
1392 pathStencilMask,
1393 pathStencilMask));
1394 GR_GL(StencilOp(GL_INVERT, GL_INCR, GL_INCR));
1395 GR_GL(Enable(GL_CULL_FACE));
1396 GR_GL(CullFace(GL_BACK));
1397 }
1398 }
1399 GR_GL(StencilMask(pathStencilMask));
1400 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1401 break;
1402 case kWindingStencil2_StencilPass:
1403 GrAssert(!fSingleStencilPassForWinding);
1404 GR_GL(Enable(GL_STENCIL_TEST));
1405 if (fHasStencilWrap) {
1406 if (stencilClip) {
1407 GR_GL(StencilFunc(GL_EQUAL,
1408 clipStencilMask,
1409 clipStencilMask));
1410 } else {
1411 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1412 }
1413 GR_GL(StencilOp(GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP));
1414 } else {
1415 GR_GL(StencilFunc(GL_NOTEQUAL, 0x0, pathStencilMask));
1416 GR_GL(StencilOp(GL_INVERT, GL_DECR, GL_DECR));
1417 }
1418 GR_GL(StencilMask(pathStencilMask));
1419 GR_GL(Enable(GL_CULL_FACE));
1420 GR_GL(CullFace(GL_FRONT));
1421 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1422 break;
1423 case kWindingColor_StencilPass: {
1424 GR_GL(Enable(GL_STENCIL_TEST));
1425 GLint funcRef = 0;
1426 GLuint funcMask = pathStencilMask;
1427 GLenum funcFunc;
1428 if (stencilClip) {
1429 funcRef |= clipStencilMask;
1430 funcMask |= clipStencilMask;
1431 }
1432 if (fCurrDrawState.fReverseFill) {
1433 funcFunc = GL_EQUAL;
1434 } else {
1435 funcFunc = GL_LESS;
1436 }
1437 GR_GL(StencilFunc(funcFunc, funcRef, funcMask));
1438 GR_GL(StencilMask(pathStencilMask));
1439 // must zero in sfail because winding w/o wrap will write
1440 // path stencil bits in clipped out pixels
1441 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1442 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1443 if (!fSingleStencilPassForWinding) {
1444 GR_GL(Disable(GL_CULL_FACE));
1445 }
1446 } break;
1447 case kSetClip_StencilPass:
1448 GR_GL(Enable(GL_STENCIL_TEST));
1449 GR_GL(StencilFunc(GL_ALWAYS, clipStencilMask, clipStencilMask));
1450 GR_GL(StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
1451 GR_GL(StencilMask(clipStencilMask));
1452 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1453 if (!fSingleStencilPassForWinding) {
1454 GR_GL(Disable(GL_CULL_FACE));
1455 }
1456 break;
1457 default:
1458 GrAssert(!"Unexpected stencil pass.");
1459 break;
1460
1461 }
1462 fHWDrawState.fStencilPass = fCurrDrawState.fStencilPass;
1463 fHWDrawState.fReverseFill = fCurrDrawState.fReverseFill;
1464 fWriteMaskChanged = false;
1465 fHWStencilClip = stencilClip;
1466 }
1467}
1468
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001469bool GrGpuGL::flushGLStateCommon(PrimitiveType type) {
1470
1471 // GrGpu::setupClipAndFlushState should have already checked this
1472 // and bailed if not true.
1473 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001474
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001475 for (int s = 0; s < kNumStages; ++s) {
1476 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001477
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001478 // bind texture and set sampler state
1479 if (usingTexture) {
1480 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001481
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001482 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001483 // if we created a rt/tex and rendered to it without using a
1484 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001485 // the last bound texture, but it needs resolving. So keep this
1486 // out of the "last != next" check.
1487 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001488
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001489 if (fHWDrawState.fTextures[s] != nextTexture) {
1490 setTextureUnit(s);
1491 GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
1492 #if GR_COLLECT_STATS
1493 ++fStats.fTextureChngCnt;
1494 #endif
1495 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1496 fHWDrawState.fTextures[s] = nextTexture;
1497 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001498
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001499 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001500 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001501 nextTexture->getTexParams();
1502 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001503
1504 newTexParams.fFilter = sampler.isFilter() ? GL_LINEAR :
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001505 GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001506 newTexParams.fWrapS =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001507 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001508 newTexParams.fWrapT =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001509 GrGLTexture::gWrapMode2GLWrap[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001510
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001511 if (newTexParams.fFilter != oldTexParams.fFilter) {
1512 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001513 GR_GL(TexParameteri(GL_TEXTURE_2D,
1514 GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001515 newTexParams.fFilter));
bsalomon@google.com316f99232011-01-13 21:28:12 +00001516 GR_GL(TexParameteri(GL_TEXTURE_2D,
1517 GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001518 newTexParams.fFilter));
1519 }
1520 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1521 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001522 GR_GL(TexParameteri(GL_TEXTURE_2D,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001523 GL_TEXTURE_WRAP_S,
1524 newTexParams.fWrapS));
1525 }
1526 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1527 setTextureUnit(s);
bsalomon@google.com316f99232011-01-13 21:28:12 +00001528 GR_GL(TexParameteri(GL_TEXTURE_2D,
1529 GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001530 newTexParams.fWrapT));
1531 }
1532 nextTexture->setTexParams(newTexParams);
1533 } else {
1534 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001535 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001536 }
1537 }
1538 }
1539
1540 flushRenderTarget();
1541
1542 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1543 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1544 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
1545 GR_GL(Enable(GL_DITHER));
1546 } else {
1547 GR_GL(Disable(GL_DITHER));
1548 }
1549 }
1550
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001551#if GR_SUPPORT_GLDESKTOP
reed@google.comac10a2d2010-12-22 21:39:39 +00001552 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1553 // smooth lines.
1554 if (fRenderTargetChanged ||
1555 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1556 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1557 GLint msaa = 0;
1558 // only perform query if we know MSAA is supported.
1559 // calling on non-MSAA target caused a crash in one environment,
1560 // though I don't think it should.
1561 if (!fAASamples[kHigh_AALevel]) {
reed@google.comac20fb92011-01-12 17:14:53 +00001562 GR_GL_GetIntegerv(GL_SAMPLE_BUFFERS, &msaa);
reed@google.comac10a2d2010-12-22 21:39:39 +00001563 }
1564 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1565 if (msaa) {
1566 GR_GL(Enable(GL_MULTISAMPLE));
1567 } else {
1568 GR_GL(Enable(GL_LINE_SMOOTH));
1569 }
1570 } else {
1571 if (msaa) {
1572 GR_GL(Disable(GL_MULTISAMPLE));
1573 }
1574 GR_GL(Disable(GL_LINE_SMOOTH));
1575 }
1576 }
1577#endif
1578
1579 bool blendOff = canDisableBlend();
1580 if (fHWBlendDisabled != blendOff) {
1581 if (blendOff) {
1582 GR_GL(Disable(GL_BLEND));
1583 } else {
1584 GR_GL(Enable(GL_BLEND));
1585 }
1586 fHWBlendDisabled = blendOff;
1587 }
1588
1589 if (!blendOff) {
1590 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1591 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1592 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1593 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1594 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1595 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1596 }
1597 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001598
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001599#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001600 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001601 for (int s = 0; s < kNumStages; ++s) {
1602 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1603 NULL == fCurrDrawState.fRenderTarget ||
1604 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001605 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001606 fCurrDrawState.fRenderTarget);
1607 }
1608#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001609
reed@google.comac10a2d2010-12-22 21:39:39 +00001610 flushStencil();
1611
1612 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001613 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001614}
1615
1616void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001617 if (fHWGeometryState.fVertexBuffer != buffer) {
1618 fHWGeometryState.fArrayPtrsDirty = true;
1619 fHWGeometryState.fVertexBuffer = buffer;
1620 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001621}
1622
1623void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1624 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1625 buffer == fGeometrySrc.fVertexBuffer));
1626
1627 if (fHWGeometryState.fVertexBuffer == buffer) {
1628 // deleting bound buffer does implied bind to 0
1629 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001630 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001631 }
1632}
1633
1634void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1635 fGeometrySrc.fIndexBuffer = buffer;
1636}
1637
1638void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1639 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1640 buffer == fGeometrySrc.fIndexBuffer));
1641
1642 if (fHWGeometryState.fIndexBuffer == buffer) {
1643 // deleting bound buffer does implied bind to 0
1644 fHWGeometryState.fIndexBuffer = NULL;
1645 }
1646}
1647
reed@google.comac10a2d2010-12-22 21:39:39 +00001648void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1649 GrAssert(NULL != renderTarget);
1650
1651 // if the bound FBO is destroyed we can't rely on the implicit bind to 0
1652 // a) we want the default RT which may not be FBO 0
1653 // b) we set more state than just FBO based on the RT
1654 // So trash the HW state to force an RT flush next time
1655 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001656 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001657 }
1658 if (fHWDrawState.fRenderTarget == renderTarget) {
1659 fHWDrawState.fRenderTarget = NULL;
1660 }
1661 if (fClipState.fStencilClipTarget == renderTarget) {
1662 fClipState.fStencilClipTarget = NULL;
1663 }
1664}
1665
1666void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001667 for (int s = 0; s < kNumStages; ++s) {
1668 if (fCurrDrawState.fTextures[s] == texture) {
1669 fCurrDrawState.fTextures[s] = NULL;
1670 }
1671 if (fHWDrawState.fTextures[s] == texture) {
1672 // deleting bound texture does implied bind to 0
1673 fHWDrawState.fTextures[s] = NULL;
1674 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001675 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001676}
1677
1678void GrGpuGL::notifyTextureRemoveRenderTarget(GrGLTexture* texture) {
1679 GrAssert(NULL != texture->asRenderTarget());
1680
1681 // if there is a pending resolve, perform it.
1682 resolveTextureRenderTarget(texture);
1683}
1684
1685bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
1686 GLenum* internalFormat,
1687 GLenum* format,
1688 GLenum* type) {
1689 switch (config) {
1690 case GrTexture::kRGBA_8888_PixelConfig:
1691 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001692 *format = GR_GL_32BPP_COLOR_FORMAT;
reed@google.com63100f92011-01-18 21:32:14 +00001693#if GR_SUPPORT_GLES
1694 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1695 // format for a BGRA is BGRA not RGBA (as on desktop)
1696 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1697#else
1698 *internalFormat = GL_RGBA;
bsalomon@google.comed3a0682011-01-18 16:54:04 +00001699#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001700 *type = GL_UNSIGNED_BYTE;
1701 break;
1702 case GrTexture::kRGB_565_PixelConfig:
1703 *format = GL_RGB;
1704 *internalFormat = GL_RGB;
1705 *type = GL_UNSIGNED_SHORT_5_6_5;
1706 break;
1707 case GrTexture::kRGBA_4444_PixelConfig:
1708 *format = GL_RGBA;
1709 *internalFormat = GL_RGBA;
1710 *type = GL_UNSIGNED_SHORT_4_4_4_4;
1711 break;
1712 case GrTexture::kIndex_8_PixelConfig:
1713 if (this->supports8BitPalette()) {
1714 *format = GR_PALETTE8_RGBA8;
1715 *internalFormat = GR_PALETTE8_RGBA8;
1716 *type = GL_UNSIGNED_BYTE; // unused I think
1717 } else {
1718 return false;
1719 }
1720 break;
1721 case GrTexture::kAlpha_8_PixelConfig:
1722 *format = GL_ALPHA;
1723 *internalFormat = GL_ALPHA;
1724 *type = GL_UNSIGNED_BYTE;
1725 break;
1726 default:
1727 return false;
1728 }
1729 return true;
1730}
1731
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001732void GrGpuGL::setTextureUnit(int unit) {
1733 GrAssert(unit >= 0 && unit < kNumStages);
1734 if (fActiveTextureUnitIdx != unit) {
1735 GR_GL(ActiveTexture(GL_TEXTURE0 + unit));
1736 fActiveTextureUnitIdx = unit;
1737 }
1738}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001739
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001740void GrGpuGL::setSpareTextureUnit() {
1741 if (fActiveTextureUnitIdx != (GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1742 GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
1743 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1744 }
1745}
1746
reed@google.comac10a2d2010-12-22 21:39:39 +00001747/* On ES the internalFormat and format must match for TexImage and we use
1748 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1749 decide the internalFormat. However, on ES internalFormat for
1750 RenderBufferStorage* has to be a specific format (not a base format like
1751 GL_RGBA).
1752 */
1753bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) {
1754 switch (config) {
1755 case GrTexture::kRGBA_8888_PixelConfig:
1756 case GrTexture::kRGBX_8888_PixelConfig:
1757 if (fRGBA8Renderbuffer) {
1758 *format = GR_RGBA8;
1759 return true;
1760 } else {
1761 return false;
1762 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001763#if GR_SUPPORT_GLES // ES2 supports 565. ES1 supports it with FBO extension
1764 // desktop GL has no such internal format
reed@google.comac10a2d2010-12-22 21:39:39 +00001765 case GrTexture::kRGB_565_PixelConfig:
1766 *format = GR_RGB565;
1767 return true;
1768#endif
1769 case GrTexture::kRGBA_4444_PixelConfig:
1770 *format = GL_RGBA4;
1771 return true;
1772 default:
1773 return false;
1774 }
1775}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001776
1777
1778const GLvoid* GrGpuGL::setBuffersAndGetVertexStart(int vertexStride, int startVertex,
1779 int startIndex, int vertexCount,
1780 int indexCount) {
1781 const GLvoid* posPtr = (GLvoid*)(vertexStride * startVertex);
1782
1783 if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
1784 GrAssert(NULL != fGeometrySrc.fVertexBuffer);
1785 GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
1786 if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
1787 GrGLVertexBuffer* buf =
1788 (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
1789 GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
1790 fHWGeometryState.fArrayPtrsDirty = true;
1791 fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
1792 }
1793 } else {
1794 if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
1795 posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
1796 (intptr_t)posPtr);
1797 } else {
1798 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
1799 posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
1800 }
1801 #if GR_GL_NO_CLIENT_SIDE_ARRAYS
1802 putClientVertexDataInBuffer(posPtr, vertexCount * vertexStride);
1803 posPtr = NULL;
1804 if (fHWGeometryState.fVertexBuffer != fClientArrayVB) {
1805 GR_GL(BindBuffer(GL_ARRAY_BUFFER, fClientArrayVB->bufferID()));
1806 fHWGeometryState.fArrayPtrsDirty = true;
1807 fHWGeometryState.fVertexBuffer = fClientArrayVB;
1808 }
1809 #else
1810 if (NULL != fHWGeometryState.fVertexBuffer) {
1811 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
1812 fHWGeometryState.fArrayPtrsDirty = true;
1813 fHWGeometryState.fVertexBuffer = NULL;
1814 }
1815 #endif
1816 }
1817
1818 if (0 != indexCount) {
1819
1820 if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1821 GrAssert(NULL != fGeometrySrc.fIndexBuffer);
1822 GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
1823 if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
1824 GrGLIndexBuffer* buf =
1825 (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1826 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
1827 fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
1828 }
1829 }
1830 #if GR_GL_NO_CLIENT_SIDE_ARRAYS
1831 else {
1832 const uint16_t* indices;
1833 if (kArray_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1834 indices = reinterpret_cast<const uint16_t*>(fGeometrySrc.fIndexArray);
1835 } else {
1836 GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fIndexSrc);
1837 indices = reinterpret_cast<const uint16_t*>(fIndices.get());
1838 }
1839 // we shove just the referenced part of the index data into the begining
1840 // of the buffer and drawIndexedHelper ignores startIndex.
1841 putClientIndexDataInBuffer(indices + startIndex, indexCount * sizeof(uint16_t));
1842 if (fHWGeometryState.fIndexBuffer != fClientArrayIB) {
1843 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, fClientArrayIB->bufferID()));
1844 fHWGeometryState.fIndexBuffer = fClientArrayIB;
1845 }
1846 }
1847 #else
1848 else if (NULL != fHWGeometryState.fIndexBuffer) {
1849 // we rely on drawIndexedHelper to pass to client side
1850 // ptr to DrawElements
1851 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
1852 fHWGeometryState.fIndexBuffer = NULL;
1853 }
1854 #endif
1855 }
1856 return posPtr;
1857}