blob: 7a7300655fea73e8a74af8886dcf6844fd8a0a0a [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"
19#include <stdio.h>
20
21static const GLuint GR_MAX_GLUINT = ~0;
22static const GLint GR_INVAL_GLINT = ~0;
23
24#define SKIP_CACHE_CHECK true
25
26static const GLenum gXfermodeCoeff2Blend[] = {
27 GL_ZERO,
28 GL_ONE,
29 GL_SRC_COLOR,
30 GL_ONE_MINUS_SRC_COLOR,
31 GL_DST_COLOR,
32 GL_ONE_MINUS_DST_COLOR,
33 GL_SRC_ALPHA,
34 GL_ONE_MINUS_SRC_ALPHA,
35 GL_DST_ALPHA,
36 GL_ONE_MINUS_DST_ALPHA,
37};
38
39bool has_gl_extension(const char* ext) {
40 const char* glstr = (const char*) glGetString(GL_EXTENSIONS);
41
42 int extLength = strlen(ext);
43
44 while (true) {
45 int n = strcspn(glstr, " ");
46 if (n == extLength && 0 == strncmp(ext, glstr, n)) {
47 return true;
48 }
49 if (0 == glstr[n]) {
50 return false;
51 }
52 glstr += n+1;
53 }
54}
55
56void gl_version(int* major, int* minor) {
57 const char* v = (const char*) glGetString(GL_VERSION);
58 if (NULL == v) {
59 GrAssert(0);
60 *major = 0;
61 *minor = 0;
62 return;
63 }
64#if GR_GL_DESKTOP
65 int n = sscanf(v, "%d.%d", major, minor);
66 if (n != 2) {
67 GrAssert(0);
68 *major = 0;
69 *minor = 0;
70 return;
71 }
72#else
73 char profile[2];
74 int n = sscanf(v, "OpenGL ES-%c%c %d.%d", profile, profile+1, major, minor);
75 bool ok = 4 == n;
76 if (!ok) {
77 int n = sscanf(v, "OpenGL ES %d.%d", major, minor);
78 ok = 2 == n;
79 }
80 if (!ok) {
81 GrAssert(0);
82 *major = 0;
83 *minor = 0;
84 return;
85 }
86#endif
87}
88///////////////////////////////////////////////////////////////////////////////
89
90bool fbo_test(GrGLExts exts, int w, int h) {
91 GLuint testFBO;
92 GR_GLEXT(exts, GenFramebuffers(1, &testFBO));
93 GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, testFBO));
94 GLuint testRTTex;
95 GR_GL(GenTextures(1, &testRTTex));
96 GR_GL(BindTexture(GL_TEXTURE_2D, testRTTex));
97
98 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h,
99 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
100 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
101 GR_GLEXT(exts, FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0,
102 GL_TEXTURE_2D, testRTTex, 0));
103 GLenum status = GR_GLEXT(exts, CheckFramebufferStatus(GR_FRAMEBUFFER));
104 GR_GLEXT(exts, DeleteFramebuffers(1, &testFBO));
105 GR_GL(DeleteTextures(1, &testRTTex));
106 return status == GR_FRAMEBUFFER_COMPLETE;
107}
108
109///////////////////////////////////////////////////////////////////////////////
110
reed@google.comeeeb5a02010-12-23 15:12:59 +0000111static bool gPrintStartupSpew;
112
reed@google.comac10a2d2010-12-22 21:39:39 +0000113GrGpuGL::GrGpuGL() {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000114 if (gPrintStartupSpew) {
115 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
116 this);
117 GrPrintf("------ VENDOR %s\n", glGetString(GL_VENDOR));
118 GrPrintf("------ RENDERER %s\n", glGetString(GL_RENDERER));
119 GrPrintf("------ VERSION %s\n", glGetString(GL_VERSION));
120 GrPrintf("------ EXTENSIONS\n %s \n", glGetString(GL_EXTENSIONS));
121 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000122
123 GrGLClearErr();
124
125 GrGLInitExtensions(&fExts);
126
127 resetContextHelper();
128
129 GrGLRenderTarget::GLRenderTargetIDs defaultRTIDs;
130 GR_GL(GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&defaultRTIDs.fRTFBOID));
131 defaultRTIDs.fTexFBOID = defaultRTIDs.fRTFBOID;
132 defaultRTIDs.fMSColorRenderbufferID = 0;
133 defaultRTIDs.fStencilRenderbufferID = 0;
134 GLint vp[4];
135 GR_GL(GetIntegerv(GL_VIEWPORT, vp));
136 fHWBounds.fViewportRect.setLTRB(vp[0],
137 vp[1] + vp[3],
138 vp[0] + vp[2],
139 vp[1]);
140 defaultRTIDs.fOwnIDs = false;
141
142 fDefaultRenderTarget = new GrGLRenderTarget(defaultRTIDs,
143 fHWBounds.fViewportRect,
144 NULL,
145 this);
146 fHWDrawState.fRenderTarget = fDefaultRenderTarget;
147 fRenderTargetChanged = true;
148
149 fCurrDrawState = fHWDrawState;
150
151 ////////////////////////////////////////////////////////////////////////////
152 // Check for supported features.
153
154 int major, minor;
155 gl_version(&major, &minor);
156
157 GLint numFormats;
158 GR_GL(GetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats));
159 GrAutoSTMalloc<10, GLint> formats(numFormats);
160 GR_GL(GetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats));
161 for (int i = 0; i < numFormats; ++i) {
162 if (formats[i] == GR_PALETTE8_RGBA8) {
163 f8bitPaletteSupport = true;
164 break;
165 }
166 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000167
168 if (gPrintStartupSpew) {
169 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
170 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000171
172 GR_STATIC_ASSERT(0 == kNone_AALevel);
173 GR_STATIC_ASSERT(1 == kLow_AALevel);
174 GR_STATIC_ASSERT(2 == kMed_AALevel);
175 GR_STATIC_ASSERT(3 == kHigh_AALevel);
176
177 memset(fAASamples, 0, sizeof(fAASamples));
178 fMSFBOType = kNone_MSFBO;
179 if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
180 fMSFBOType = kIMG_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000181 if (gPrintStartupSpew) {
182 GrPrintf("MSAA Support: IMG ES EXT.\n");
183 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000184 }
185 else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
186 fMSFBOType = kApple_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000187 if (gPrintStartupSpew) {
188 GrPrintf("MSAA Support: APPLE ES EXT.\n");
189 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000190 }
191#if GR_GL_DESKTOP
192 else if ((major >= 3) ||
193 has_gl_extension("GL_ARB_framebuffer_object") ||
194 (has_gl_extension("GL_EXT_framebuffer_multisample") &&
195 has_gl_extension("GL_EXT_framebuffer_blit"))) {
196 fMSFBOType = kDesktop_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000197 if (gPrintStartupSpew) {
198 GrPrintf("MSAA Support: DESKTOP\n");
199 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000200 }
201#endif
202 else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000203 if (gPrintStartupSpew) {
204 GrPrintf("MSAA Support: NONE\n");
205 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000206 }
207
208 if (kNone_MSFBO != fMSFBOType) {
209 GLint maxSamples;
210 GLenum maxSampleGetter = (kIMG_MSFBO == fMSFBOType) ?
211 GR_MAX_SAMPLES_IMG :
212 GR_MAX_SAMPLES;
213 GR_GL(GetIntegerv(maxSampleGetter, &maxSamples));
214 if (maxSamples > 1 ) {
215 fAASamples[kNone_AALevel] = 0;
216 fAASamples[kLow_AALevel] = GrMax(2,
217 GrFixedFloorToInt((GR_FixedHalf) *
218 maxSamples));
219 fAASamples[kMed_AALevel] = GrMax(2,
220 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
221 maxSamples));
222 fAASamples[kHigh_AALevel] = maxSamples;
223 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000224 if (gPrintStartupSpew) {
225 GrPrintf("\tMax Samples: %d\n", maxSamples);
226 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000227 }
228
229#if GR_GL_DESKTOP
230 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
231 has_gl_extension("GL_EXT_stencil_wrap");
232#else
233 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
234#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000235 if (gPrintStartupSpew) {
236 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
237 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000238
239#if GR_GL_DESKTOP
240 // we could also look for GL_ATI_separate_stencil extension or
241 // GL_EXT_stencil_two_side but they use different function signatures
242 // than GL2.0+ (and than each other).
243 fSingleStencilPassForWinding = (major >= 2);
244#else
245 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
246 // an ES1 extension.
247 fSingleStencilPassForWinding = (major >= 2);
248#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000249 if (gPrintStartupSpew) {
250 GrPrintf("Single Stencil Pass For Winding: %s\n", (fSingleStencilPassForWinding ? "YES" : "NO"));
251 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000252
253
254#if GR_GL_DESKTOP
255 fRGBA8Renderbuffer = true;
256#else
257 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
258#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000259 if (gPrintStartupSpew) {
260 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
261 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000262
263
264#if GR_GL_DESKTOP
265 fBufferLockSupport = true; // we require VBO support and the desktop VBO
266 // extension includes glMapBuffer.
267#else
268 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
269#endif
reed@google.comeeeb5a02010-12-23 15:12:59 +0000270 if (gPrintStartupSpew) {
271 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
272 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000273
274#if GR_GL_DESKTOP
275 fNPOTTextureSupport =
276 (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) ?
277 kFull_NPOTTextureType :
278 kNone_NPOTTextureType;
279#else
280 if (has_gl_extension("GL_OES_texture_npot")) {
281 fNPOTTextureSupport = kFull_NPOTTextureType;
282 } else if (major >= 2 ||
283 has_gl_extension("GL_APPLE_texture_2D_limited_npot")) {
284 fNPOTTextureSupport = kNoRepeat_NPOTTextureType;
285 } else {
286 fNPOTTextureSupport = kNone_NPOTTextureType;
287 }
288#endif
289 ////////////////////////////////////////////////////////////////////////////
290 // Experiments to determine limitations that can't be queried. TODO: Make
291 // these a preprocess that generate some compile time constants.
292
293 /* Experimentation has found that some GLs that support NPOT textures
294 do not support FBOs with a NPOT texture. They report "unsupported" FBO
295 status. I don't know how to explicitly query for this. Do an
296 experiment. Note they may support NPOT with a renderbuffer but not a
297 texture. Presumably, the implementation bloats the renderbuffer
298 internally to the next POT.
299 */
300 if (fNPOTTextureSupport == kFull_NPOTTextureType) {
301 bool npotFBOSuccess = fbo_test(fExts, 200, 200);
302 if (!npotFBOSuccess) {
303 fNPOTTextureSupport = kNonRendertarget_NPOTTextureType;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000304 if (gPrintStartupSpew) {
305 GrPrintf("NPOT Renderbuffer Test: FAILED\n");
306 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000307 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000308 if (gPrintStartupSpew) {
309 GrPrintf("NPOT Renderbuffer Test: PASSED\n");
310 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000311 }
312 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000313
314 if (gPrintStartupSpew) {
315 switch (fNPOTTextureSupport) {
316 case kNone_NPOTTextureType:
317 GrPrintf("NPOT Support: NONE\n");
318 break;
319 case kNoRepeat_NPOTTextureType:
320 GrPrintf("NPOT Support: NO REPEAT\n");
321 break;
322 case kNonRendertarget_NPOTTextureType:
323 GrPrintf("NPOT Support: NO FBOTEX\n");
324 break;
325 case kFull_NPOTTextureType:
326 GrPrintf("NPOT Support: FULL\n");
327 break;
328 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000329 }
330
331 // sanity check to make sure we can at least create an FBO from a POT texture
332 if (fNPOTTextureSupport < kFull_NPOTTextureType) {
333 bool npotFBOSuccess = fbo_test(fExts, 128, 128);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000334 if (gPrintStartupSpew) {
335 if (!npotFBOSuccess) {
336 GrPrintf("FBO Sanity Test: FAILED\n");
337 } else {
338 GrPrintf("FBO Sanity Test: PASSED\n");
339 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000340 }
341 }
342
343 /* The iPhone 4 has a restriction that for an FBO with texture color
344 attachment with height <= 8 then the width must be <= height. Here
345 we look for such a limitation.
346 */
347 fMinRenderTargetHeight = GR_INVAL_GLINT;
348 GLint maxRenderSize;
349 glGetIntegerv(GR_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
350
reed@google.comeeeb5a02010-12-23 15:12:59 +0000351 if (gPrintStartupSpew) {
352 GrPrintf("Small height FBO texture experiments\n");
353 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000354 for (GLuint i = 1; i <= 256;
355 (kFull_NPOTTextureType != fNPOTTextureSupport) ? i *= 2 : ++i) {
356 GLuint w = maxRenderSize;
357 GLuint h = i;
358 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000359 if (gPrintStartupSpew) {
360 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
361 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000362 fMinRenderTargetHeight = i;
363 break;
364 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000365 if (gPrintStartupSpew) {
366 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
367 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000368 }
369 }
370 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
371
reed@google.comeeeb5a02010-12-23 15:12:59 +0000372 if (gPrintStartupSpew) {
373 GrPrintf("Small width FBO texture experiments\n");
374 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000375 fMinRenderTargetWidth = GR_MAX_GLUINT;
376 for (GLuint i = 1; i <= 256;
377 (kFull_NPOTTextureType != fNPOTTextureSupport) ? i *= 2 : ++i) {
378 GLuint w = i;
379 GLuint h = maxRenderSize;
380 if (fbo_test(fExts, w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000381 if (gPrintStartupSpew) {
382 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
383 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000384 fMinRenderTargetWidth = i;
385 break;
386 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000387 if (gPrintStartupSpew) {
388 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
389 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000390 }
391 }
392 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
393
394#if GR_IOS_BUILD
395 /*
396 The iPad seems to fail, at least sometimes, if the height is < 16,
397 so we pin the values here for now. A better fix might be to
398 conditionalize this based on known that its an iPad (or some other
399 check).
400 */
401 fMinRenderTargetWidth = GrMax<GLuint>(fMinRenderTargetWidth, 16);
402 fMinRenderTargetHeight = GrMax<GLuint>(fMinRenderTargetHeight, 16);
403#endif
404 // bind back to original FBO
405 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, defaultRTIDs.fRTFBOID));
406#if GR_COLLECT_STATS
407 ++fStats.fRenderTargetChngCnt;
408#endif
409 eraseStencil(0, ~0);
410}
411
412GrGpuGL::~GrGpuGL() {
413 fDefaultRenderTarget->abandon();
414 fDefaultRenderTarget->unref();
415}
416
417void GrGpuGL::resetContextHelper() {
418// We detect cases when blending is effectively off
419 fHWBlendDisabled = false;
420 GR_GL(Enable(GL_BLEND));
421
422 // this is always disabled
423 GR_GL(Disable(GL_CULL_FACE));
424
425 GR_GL(Disable(GL_DITHER));
426#if GR_GL_DESKTOP
427 GR_GL(Disable(GL_LINE_SMOOTH));
428 GR_GL(Disable(GL_POINT_SMOOTH));
429 GR_GL(Disable(GL_MULTISAMPLE));
430#endif
431
432 // we only ever use lines in hairline mode
433 GR_GL(LineWidth(1));
434
435 GR_GL(ActiveTexture(GL_TEXTURE0));
436
437 fHWDrawState.fFlagBits = 0;
438
439 // illegal values
440 fHWDrawState.fSrcBlend = (BlendCoeff)-1;
441 fHWDrawState.fDstBlend = (BlendCoeff)-1;
442 fHWDrawState.fColor = GrColor_ILLEGAL;
443 fHWDrawState.fPointSize = -1;
444 fHWDrawState.fTexture = NULL;
445
446 GR_GL(Scissor(0,0,0,0));
447 fHWBounds.fScissorRect.setLTRB(0,0,0,0);
448 fHWBounds.fScissorEnabled = false;
449 GR_GL(Disable(GL_SCISSOR_TEST));
450
451 fHWDrawState.fSamplerState.setRadial2Params(-GR_ScalarMax,
452 -GR_ScalarMax,
453 true);
454
455 for (int i = 0; i < kMatrixModeCount; i++) {
456 fHWDrawState.fMatrixModeCache[i].setScale(GR_ScalarMax, GR_ScalarMax); // illegal
457 }
458
459 // disabling the stencil test also disables
460 // stencil buffer writes
461 GR_GL(Disable(GL_STENCIL_TEST));
462 GR_GL(StencilMask(0xffffffff));
463 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
464 fHWDrawState.fReverseFill = false;
465 fHWDrawState.fStencilPass = kNone_StencilPass;
466 fHWStencilClip = false;
467
468 fHWGeometryState.fIndexBuffer = NULL;
469 fHWGeometryState.fVertexBuffer = NULL;
470 GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
471 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
472
473 fHWDrawState.fRenderTarget = NULL;
474}
475
476void GrGpuGL::resetContext() {
477 INHERITED::resetContext();
478 resetContextHelper();
479}
480
481
482// defines stencil formats from more to less preferred
483#if GR_GL_ES
484 GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = {
485 GR_STENCIL_INDEX8,
486 };
487#else
488 GLenum GR_GL_STENCIL_FORMAT_ARRAY[] = {
489 GR_STENCIL_INDEX8,
490 GR_STENCIL_INDEX16,
491 GR_UNSIGNED_INT_24_8,
492 GR_DEPTH_STENCIL,
493 };
494#endif
495
496// good to set a break-point here to know when createTexture fails
497static GrTexture* return_null_texture() {
498// GrAssert(!"null texture");
499 return NULL;
500}
501
502#if GR_DEBUG
503static size_t as_size_t(int x) {
504 return x;
505}
506#endif
507
508GrRenderTarget* GrGpuGL::createPlatformRenderTarget(
509 intptr_t platformRenderTarget,
510 int width, int height) {
511 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
512 rtIDs.fStencilRenderbufferID = 0;
513 rtIDs.fMSColorRenderbufferID = 0;
514 rtIDs.fTexFBOID = 0;
515 rtIDs.fOwnIDs = false;
516
517 GrIRect viewport;
518
519 // viewport is in GL coords (top >= bottom)
520 viewport.setLTRB(0, height, width, 0);
521
522 rtIDs.fRTFBOID = (GLuint)platformRenderTarget;
523 rtIDs.fTexFBOID = (GLuint)platformRenderTarget;
524
525 GrGLRenderTarget* rt = new GrGLRenderTarget(rtIDs, viewport, NULL, this);
526
527 return rt;
528}
529
530GrTexture* GrGpuGL::createTexture(const TextureDesc& desc,
531 const void* srcData, size_t rowBytes) {
532
533#if GR_COLLECT_STATS
534 ++fStats.fTextureCreateCnt;
535#endif
536 GrGLTexture::GLTextureDesc glDesc;
537 GLenum internalFormat;
538
539 glDesc.fContentWidth = desc.fWidth;
540 glDesc.fContentHeight = desc.fHeight;
541 glDesc.fAllocWidth = desc.fWidth;
542 glDesc.fAllocHeight = desc.fHeight;
543 glDesc.fFormat = desc.fFormat;
544
545 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
546 if (!canBeTexture(desc.fFormat,
547 &internalFormat,
548 &glDesc.fUploadFormat,
549 &glDesc.fUploadType)) {
550 return return_null_texture();
551 }
552
553 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
554 GLint samples = fAASamples[desc.fAALevel];
555 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
556 GrPrintf("AA RT requested but not supported on this platform.");
557 }
558
559 GR_GL(GenTextures(1, &glDesc.fTextureID));
560 if (!glDesc.fTextureID) {
561 return return_null_texture();
562 }
563
564 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
565
566 /*
567 * check if our srcData has extra bytes past each row. If so, we need
568 * to trim those off here, since GL doesn't let us pass the rowBytes as
569 * a parameter to glTexImage2D
570 */
571#if GR_GL_DESKTOP
572 if (srcData) {
573 GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH,
574 rowBytes / glDesc.fUploadByteCount));
575 }
576#else
577 GrAutoSMalloc<128 * 128> trimStorage;
578 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
579 if (srcData && (trimRowBytes < rowBytes)) {
580 size_t trimSize = desc.fHeight * trimRowBytes;
581 trimStorage.realloc(trimSize);
582 // now copy the data into our new storage, skipping the trailing bytes
583 const char* src = (const char*)srcData;
584 char* dst = (char*)trimStorage.get();
585 for (uint32_t y = 0; y < desc.fHeight; y++) {
586 memcpy(dst, src, trimRowBytes);
587 src += rowBytes;
588 dst += trimRowBytes;
589 }
590 // now point srcData to our trimmed version
591 srcData = trimStorage.get();
592 }
593#endif
594
595 if (fNPOTTextureSupport < kNonRendertarget_NPOTTextureType ||
596 (fNPOTTextureSupport == kNonRendertarget_NPOTTextureType &&
597 renderTarget)) {
598 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
599 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
600 }
601
602 if (renderTarget) {
603 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
604 glDesc.fAllocWidth);
605 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
606 glDesc.fAllocHeight);
607 }
608
609 GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID));
610#if GR_COLLECT_STATS
611 ++fStats.fTextureChngCnt;
612#endif
613
614 GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
615 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
616 supports8BitPalette()) {
617 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
618 GrAssert(desc.fWidth == glDesc.fAllocWidth);
619 GrAssert(desc.fHeight == glDesc.fAllocHeight);
620 GLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
621 kColorTableSize;
622 GR_GL(CompressedTexImage2D(GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
623 glDesc.fAllocWidth, glDesc.fAllocHeight,
624 0, imageSize, srcData));
625 GrGL_RestoreResetRowLength();
626 } else {
627 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
628 glDesc.fAllocHeight != desc.fHeight)) {
629 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat,
630 glDesc.fAllocWidth, glDesc.fAllocHeight,
631 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
632 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
633 desc.fHeight, glDesc.fUploadFormat,
634 glDesc.fUploadType, srcData));
635 GrGL_RestoreResetRowLength();
636
637 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
638 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
639 uint32_t maxTexels = extraW * extraH;
640 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
641 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
642
643 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
644
645 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
646 if (extraH) {
647 uint8_t* lastRowStart = (uint8_t*) srcData +
648 (desc.fHeight - 1) * rowSize;
649 uint8_t* extraRowStart = (uint8_t*)texels.get();
650
651 for (uint32_t i = 0; i < extraH; ++i) {
652 memcpy(extraRowStart, lastRowStart, rowSize);
653 extraRowStart += rowSize;
654 }
655 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
656 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
657 texels.get()));
658 }
659 if (extraW) {
660 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
661 uint8_t* extraTexel = (uint8_t*)texels.get();
662 for (uint32_t j = 0; j < desc.fHeight; ++j) {
663 for (uint32_t i = 0; i < extraW; ++i) {
664 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
665 extraTexel += glDesc.fUploadByteCount;
666 }
667 edgeTexel += rowSize;
668 }
669 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
670 desc.fHeight, glDesc.fUploadFormat,
671 glDesc.fUploadType, texels.get()));
672 }
673 if (extraW && extraH) {
674 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
675 - glDesc.fUploadByteCount;
676 uint8_t* extraTexel = (uint8_t*)texels.get();
677 for (uint32_t i = 0; i < extraW*extraH; ++i) {
678 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
679 extraTexel += glDesc.fUploadByteCount;
680 }
681 GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
682 extraW, extraH, glDesc.fUploadFormat,
683 glDesc.fUploadType, texels.get()));
684 }
685
686 } else {
687 GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
688 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
689 glDesc.fUploadType, srcData));
690 GrGL_RestoreResetRowLength();
691 }
692 }
693
694 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
695
696 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
697 rtIDs.fStencilRenderbufferID = 0;
698 rtIDs.fMSColorRenderbufferID = 0;
699 rtIDs.fRTFBOID = 0;
700 rtIDs.fTexFBOID = 0;
701 rtIDs.fOwnIDs = true;
702 GLenum msColorRenderbufferFormat = -1;
703
704 if (renderTarget) {
705#if GR_COLLECT_STATS
706 ++fStats.fRenderTargetCreateCnt;
707#endif
708 bool failed = true;
709 GLenum status;
710 GLint err;
711
712 // If need have both RT flag and srcData we have
713 // to invert the data before uploading because FBO
714 // will be rendered bottom up
715 GrAssert(NULL == srcData);
716 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
717
718 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fTexFBOID));
719 GrAssert(rtIDs.fTexFBOID);
720
721 // If we are using multisampling and any extension other than the IMG
722 // one we will create two FBOs. We render to one and then resolve to
723 // the texture bound to the other. The IMG extension does an implicit
724 // resolve.
725 if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
726 GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fRTFBOID));
727 GrAssert(0 != rtIDs.fRTFBOID);
728 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
729 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
730 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
731 GR_GLEXT(fExts,
732 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
733 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
734 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
735 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
736 fHWDrawState.fTexture = NULL;
737 return return_null_texture();
738 }
739 } else {
740 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
741 }
742 int attempts = 1;
743 if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
744 GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
745 GrAssert(0 != rtIDs.fStencilRenderbufferID);
746 attempts = GR_ARRAY_COUNT(GR_GL_STENCIL_FORMAT_ARRAY);
747 }
748
749 // need to unbind the texture before we call FramebufferTexture2D
750 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
751#if GR_COLLECT_STATS
752 ++fStats.fTextureChngCnt;
753#endif
754
755 fHWDrawState.fTexture = NULL;
756
757 err = ~GL_NO_ERROR;
758 for (int i = 0; i < attempts; ++i) {
759 if (rtIDs.fStencilRenderbufferID) {
760 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
761 rtIDs.fStencilRenderbufferID));
762 if (samples > 1) {
763 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
764 GR_RENDERBUFFER,
765 samples,
766 GR_GL_STENCIL_FORMAT_ARRAY[i],
767 glDesc.fAllocWidth,
768 glDesc.fAllocHeight));
769 } else {
770 GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
771 GR_RENDERBUFFER,
772 GR_GL_STENCIL_FORMAT_ARRAY[i],
773 glDesc.fAllocWidth,
774 glDesc.fAllocHeight));
775 }
776 err = glGetError();
777 if (err != GL_NO_ERROR) {
778 continue;
779 }
780 }
781 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
782 GrAssert(samples > 1);
783 GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
784 rtIDs.fMSColorRenderbufferID));
785 GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
786 GR_RENDERBUFFER,
787 samples,
788 msColorRenderbufferFormat,
789 glDesc.fAllocWidth,
790 glDesc.fAllocHeight));
791 err = glGetError();
792 if (err != GL_NO_ERROR) {
793 continue;
794 }
795 }
796 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
797
798#if GR_COLLECT_STATS
799 ++fStats.fRenderTargetChngCnt;
800#endif
801 if (kIMG_MSFBO == fMSFBOType && samples > 1) {
802 GR_GLEXT(fExts, FramebufferTexture2DMultisample(
803 GR_FRAMEBUFFER,
804 GR_COLOR_ATTACHMENT0,
805 GL_TEXTURE_2D,
806 glDesc.fTextureID,
807 0,
808 samples));
809
810 } else {
811 GR_GLEXT(fExts, FramebufferTexture2D(GR_FRAMEBUFFER,
812 GR_COLOR_ATTACHMENT0,
813 GL_TEXTURE_2D,
814 glDesc.fTextureID, 0));
815 }
816 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
817 GLenum status = GR_GLEXT(fExts,
818 CheckFramebufferStatus(GR_FRAMEBUFFER));
819 if (status != GR_FRAMEBUFFER_COMPLETE) {
820 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
821 status, desc.fWidth, desc.fHeight);
822 continue;
823 }
824 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
825 #if GR_COLLECT_STATS
826 ++fStats.fRenderTargetChngCnt;
827 #endif
828 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
829 GR_COLOR_ATTACHMENT0,
830 GR_RENDERBUFFER,
831 rtIDs.fMSColorRenderbufferID));
832
833 }
834 if (rtIDs.fStencilRenderbufferID) {
835 // bind the stencil to rt fbo if present, othewise the tex fbo
836 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
837 GR_STENCIL_ATTACHMENT,
838 GR_RENDERBUFFER,
839 rtIDs.fStencilRenderbufferID));
840 }
841 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
842
843#if GR_GL_DESKTOP
844 // On some implementations you have to be bound as DEPTH_STENCIL.
845 // (Even binding to DEPTH and STENCIL separately with the same
846 // buffer doesn't work.)
847 if (rtIDs.fStencilRenderbufferID &&
848 status != GR_FRAMEBUFFER_COMPLETE) {
849 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
850 GR_STENCIL_ATTACHMENT,
851 GR_RENDERBUFFER,
852 0));
853 GR_GLEXT(fExts,
854 FramebufferRenderbuffer(GR_FRAMEBUFFER,
855 GR_DEPTH_STENCIL_ATTACHMENT,
856 GR_RENDERBUFFER,
857 rtIDs.fStencilRenderbufferID));
858 status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
859 }
860#endif
861 if (status != GR_FRAMEBUFFER_COMPLETE) {
862 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
863 status, desc.fWidth, desc.fHeight);
864#if GR_GL_DESKTOP
865 if (rtIDs.fStencilRenderbufferID) {
866 GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
867 GR_DEPTH_STENCIL_ATTACHMENT,
868 GR_RENDERBUFFER,
869 0));
870 }
871#endif
872 continue;
873 }
874 // we're successful!
875 failed = false;
876 break;
877 }
878 if (failed) {
879 if (rtIDs.fStencilRenderbufferID) {
880 GR_GLEXT(fExts,
881 DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
882 }
883 if (rtIDs.fMSColorRenderbufferID) {
884 GR_GLEXT(fExts,
885 DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
886 }
887 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
888 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
889 }
890 if (rtIDs.fTexFBOID) {
891 GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
892 }
893 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
894 return return_null_texture();
895 }
896 }
897#ifdef TRACE_TEXTURE_CREATION
898 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
899 tex->fTextureID, width, height, tex->fUploadByteCount);
900#endif
901 GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, this);
902
903 if (0 != rtIDs.fTexFBOID) {
904 GrRenderTarget* rt = tex->asRenderTarget();
905 // We've messed with FBO state but may not have set the correct viewport
906 // so just dirty the rendertarget state to force a resend.
907 fHWDrawState.fRenderTarget = NULL;
908
909 // clear the new stencil buffer if we have one
910 if (!(desc.fFlags & kNoPathRendering_TextureFlag)) {
911 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
912 fCurrDrawState.fRenderTarget = rt;
913 eraseStencil(0, ~0);
914 fCurrDrawState.fRenderTarget = rtSave;
915 }
916 }
917 return tex;
918}
919
920GrRenderTarget* GrGpuGL::defaultRenderTarget() {
921 return fDefaultRenderTarget;
922}
923
924GrVertexBuffer* GrGpuGL::createVertexBuffer(uint32_t size, bool dynamic) {
925 GLuint id;
926 GR_GL(GenBuffers(1, &id));
927 if (id) {
928 GR_GL(BindBuffer(GL_ARRAY_BUFFER, id));
929 GrGLClearErr();
930 // make sure driver can allocate memory for this buffer
931 GR_GL_NO_ERR(BufferData(GL_ARRAY_BUFFER, size, NULL,
932 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
933 if (glGetError() != GL_NO_ERROR) {
934 GR_GL(DeleteBuffers(1, &id));
935 // deleting bound buffer does implicit bind to 0
936 fHWGeometryState.fVertexBuffer = NULL;
937 return NULL;
938 }
939 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this,
940 size, dynamic);
941 fHWGeometryState.fVertexBuffer = vertexBuffer;
942 return vertexBuffer;
943 }
944 return NULL;
945}
946
947GrIndexBuffer* GrGpuGL::createIndexBuffer(uint32_t size, bool dynamic) {
948 GLuint id;
949 GR_GL(GenBuffers(1, &id));
950 if (id) {
951 GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, id));
952 GrGLClearErr();
953 // make sure driver can allocate memory for this buffer
954 GR_GL_NO_ERR(BufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL,
955 dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
956 if (glGetError() != GL_NO_ERROR) {
957 GR_GL(DeleteBuffers(1, &id));
958 // deleting bound buffer does implicit bind to 0
959 fHWGeometryState.fIndexBuffer = NULL;
960 return NULL;
961 }
962 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this,
963 size, dynamic);
964 fHWGeometryState.fIndexBuffer = indexBuffer;
965 return indexBuffer;
966 }
967 return NULL;
968}
969
970void GrGpuGL::setDefaultRenderTargetSize(uint32_t width, uint32_t height) {
971 GrIRect viewport(0, height, width, 0);
972 if (viewport != fDefaultRenderTarget->viewport()) {
973 fDefaultRenderTarget->setViewport(viewport);
974 if (fHWDrawState.fRenderTarget == fDefaultRenderTarget) {
975 fHWDrawState.fRenderTarget = NULL;
976 }
977 }
978}
979
980void GrGpuGL::flushScissor(const GrIRect* rect) {
981 GrAssert(NULL != fCurrDrawState.fRenderTarget);
982 const GrIRect& vp =
983 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
984
985 if (NULL != rect &&
986 rect->contains(vp)) {
987 rect = NULL;
988 }
989
990 if (NULL != rect) {
991 GrIRect scissor;
992 // viewport is already in GL coords
993 // create a scissor in GL coords (top > bottom)
994 scissor.setLTRB(vp.fLeft + rect->fLeft,
995 vp.fTop - rect->fTop,
996 vp.fLeft + rect->fRight,
997 vp.fTop - rect->fBottom);
998
999 if (fHWBounds.fScissorRect != scissor) {
1000 GR_GL(Scissor(scissor.fLeft, scissor.fBottom,
1001 scissor.width(), -scissor.height()));
1002 fHWBounds.fScissorRect = scissor;
1003 }
1004
1005 if (!fHWBounds.fScissorEnabled) {
1006 GR_GL(Enable(GL_SCISSOR_TEST));
1007 fHWBounds.fScissorEnabled = true;
1008 }
1009 } else {
1010 if (fHWBounds.fScissorEnabled) {
1011 GR_GL(Disable(GL_SCISSOR_TEST));
1012 fHWBounds.fScissorEnabled = false;
1013 }
1014 }
1015}
1016
1017void GrGpuGL::setSamplerStateImm(const GrSamplerState& state) {
1018
1019 GLenum filter = state.isFilter() ? GL_LINEAR : GL_NEAREST;
1020 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter));
1021 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter));
1022 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1023 GrGLTexture::gWrapMode2GLWrap[state.getWrapX()]));
1024 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1025 GrGLTexture::gWrapMode2GLWrap[state.getWrapY()]));
1026
1027}
1028
1029void GrGpuGL::eraseColor(GrColor color) {
1030 flushRenderTarget();
1031 if (fHWBounds.fScissorEnabled) {
1032 GR_GL(Disable(GL_SCISSOR_TEST));
1033 }
1034 GR_GL(ColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE));
1035 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1036 GrColorUnpackG(color)/255.f,
1037 GrColorUnpackB(color)/255.f,
1038 GrColorUnpackA(color)/255.f));
1039 GR_GL(Clear(GL_COLOR_BUFFER_BIT));
1040 fHWBounds.fScissorEnabled = false;
1041 fWriteMaskChanged = true;
1042}
1043
1044void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
1045 flushRenderTarget();
1046 if (fHWBounds.fScissorEnabled) {
1047 GR_GL(Disable(GL_SCISSOR_TEST));
1048 }
1049 GR_GL(StencilMask(mask));
1050 GR_GL(ClearStencil(value));
1051 GR_GL(Clear(GL_STENCIL_BUFFER_BIT));
1052 fHWBounds.fScissorEnabled = false;
1053 fWriteMaskChanged = true;
1054}
1055
1056void GrGpuGL::eraseStencilClip() {
1057 GLint stencilBitCount;
1058 GR_GL(GetIntegerv(GL_STENCIL_BITS, &stencilBitCount));
1059 GrAssert(stencilBitCount > 0);
1060 GLint clipStencilMask = (1 << (stencilBitCount - 1));
1061 eraseStencil(0, clipStencilMask);
1062}
1063
1064void GrGpuGL::forceRenderTargetFlush() {
1065 flushRenderTarget();
1066}
1067
1068bool GrGpuGL::readPixels(int left, int top, int width, int height,
1069 GrTexture::PixelConfig config, void* buffer) {
1070 GLenum internalFormat; // we don't use this for glReadPixels
1071 GLenum format;
1072 GLenum type;
1073 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1074 return false;
1075 }
1076
1077 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1078 const GrIRect& vp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->viewport();
1079
1080 // Brian says that viewport rects are already upside down (grrrrr)
1081 glReadPixels(left, -vp.height() - top - height, width, height,
1082 format, type, buffer);
1083
1084 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1085 // API presents top-to-bottom
1086 {
1087 size_t stride = width * GrTexture::BytesPerPixel(config);
1088 GrAutoMalloc rowStorage(stride);
1089 void* tmp = rowStorage.get();
1090
1091 const int halfY = height >> 1;
1092 char* top = reinterpret_cast<char*>(buffer);
1093 char* bottom = top + (height - 1) * stride;
1094 for (int y = 0; y < halfY; y++) {
1095 memcpy(tmp, top, stride);
1096 memcpy(top, bottom, stride);
1097 memcpy(bottom, tmp, stride);
1098 top += stride;
1099 bottom -= stride;
1100 }
1101 }
1102 return true;
1103}
1104
1105void GrGpuGL::flushRenderTarget() {
1106 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1107 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
1108 GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
1109 #if GR_COLLECT_STATS
1110 ++fStats.fRenderTargetChngCnt;
1111 #endif
1112 rt->setDirty(true);
1113 #if GR_DEBUG
1114 GLenum status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
1115 if (status != GR_FRAMEBUFFER_COMPLETE) {
1116 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1117 }
1118 #endif
1119 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
1120 const GrIRect& vp = rt->viewport();
1121 fRenderTargetChanged = true;
1122 if (fHWBounds.fViewportRect != vp) {
1123 GR_GL(Viewport(vp.fLeft,
1124 vp.fBottom,
1125 vp.width(),
1126 -vp.height()));
1127 fHWBounds.fViewportRect = vp;
1128 }
1129 }
1130}
1131
1132GLenum gPrimitiveType2GLMode[] = {
1133 GL_TRIANGLES,
1134 GL_TRIANGLE_STRIP,
1135 GL_TRIANGLE_FAN,
1136 GL_POINTS,
1137 GL_LINES,
1138 GL_LINE_STRIP
1139};
1140
1141void GrGpuGL::drawIndexedHelper(PrimitiveType type,
1142 uint32_t startVertex,
1143 uint32_t startIndex,
1144 uint32_t vertexCount,
1145 uint32_t indexCount) {
1146 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1147
1148 GLvoid* indices = (GLvoid*)(sizeof(uint16_t) * startIndex);
1149 if (kReserved_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1150 indices = (GLvoid*)((intptr_t)indices + (intptr_t)fIndices.get());
1151 } else if (kArray_GeometrySrcType == fGeometrySrc.fIndexSrc) {
1152 indices = (GLvoid*)((intptr_t)indices +
1153 (intptr_t)fGeometrySrc.fIndexArray);
1154 }
1155
1156 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1157 GL_UNSIGNED_SHORT, indices));
1158}
1159
1160void GrGpuGL::drawNonIndexedHelper(PrimitiveType type,
1161 uint32_t startVertex,
1162 uint32_t vertexCount) {
1163 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1164
1165 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1166}
1167
1168#if !defined(SK_GL_HAS_COLOR4UB)
1169static inline GrFixed byte2fixed(unsigned value) {
1170 return (value + (value >> 7)) << 8;
1171}
1172#endif
1173
1174void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1175 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1176
1177 if (NULL != rt && rt->needsResolve()) {
1178 GrAssert(kNone_MSFBO != fMSFBOType);
1179 GrAssert(rt->textureFBOID() != rt->renderFBOID());
1180 GR_GLEXT(fExts, BindFramebuffer(GR_READ_FRAMEBUFFER,
1181 rt->renderFBOID()));
1182 GR_GLEXT(fExts, BindFramebuffer(GR_DRAW_FRAMEBUFFER,
1183 rt->textureFBOID()));
1184 #if GR_COLLECT_STATS
1185 ++fStats.fRenderTargetChngCnt;
1186 #endif
1187 // make sure we go through set render target
1188 fHWDrawState.fRenderTarget = NULL;
1189
1190 GLint left = 0;
1191 GLint right = texture->contentWidth();
1192 // we will have rendered to the top of the FBO.
1193 GLint top = texture->allocHeight();
1194 GLint bottom = texture->allocHeight() - texture->contentHeight();
1195 if (kApple_MSFBO == fMSFBOType) {
1196 GR_GL(Enable(GL_SCISSOR_TEST));
1197 GR_GL(Scissor(left, bottom, right-left, top-bottom));
1198 GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
1199 fHWBounds.fScissorRect.setEmpty();
1200 fHWBounds.fScissorEnabled = true;
1201 } else {
1202 GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
1203 left, bottom, right, top,
1204 GL_COLOR_BUFFER_BIT, GL_NEAREST));
1205 }
1206 rt->setDirty(false);
1207
1208 }
1209}
1210
1211void GrGpuGL::flushStencil() {
1212
1213 // use stencil for clipping if clipping is enabled and the clip
1214 // has been written into the stencil.
1215 bool stencilClip = fClipState.fClipInStencil &&
1216 (kClip_StateBit & fCurrDrawState.fFlagBits);
1217 bool stencilChange =
1218 fWriteMaskChanged ||
1219 fHWStencilClip != stencilClip ||
1220 fHWDrawState.fStencilPass != fCurrDrawState.fStencilPass ||
1221 (kNone_StencilPass != fCurrDrawState.fStencilPass &&
1222 (StencilPass)kSetClip_StencilPass != fCurrDrawState.fStencilPass &&
1223 fHWDrawState.fReverseFill != fCurrDrawState.fReverseFill);
1224
1225 if (stencilChange) {
1226 GLint stencilBitCount;
1227 GLint clipStencilMask;
1228 GLint pathStencilMask;
1229 GR_GL(GetIntegerv(GL_STENCIL_BITS, &stencilBitCount));
1230 GrAssert(stencilBitCount > 0 ||
1231 kNone_StencilPass == fCurrDrawState.fStencilPass);
1232 clipStencilMask = (1 << (stencilBitCount - 1));
1233 pathStencilMask = clipStencilMask - 1;
1234 switch (fCurrDrawState.fStencilPass) {
1235 case kNone_StencilPass:
1236 if (stencilClip) {
1237 GR_GL(Enable(GL_STENCIL_TEST));
1238 GR_GL(StencilFunc(GL_EQUAL,
1239 clipStencilMask,
1240 clipStencilMask));
1241 GR_GL(StencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
1242 } else {
1243 GR_GL(Disable(GL_STENCIL_TEST));
1244 }
1245 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1246 if (!fSingleStencilPassForWinding) {
1247 GR_GL(Disable(GL_CULL_FACE));
1248 }
1249 break;
1250 case kEvenOddStencil_StencilPass:
1251 GR_GL(Enable(GL_STENCIL_TEST));
1252 if (stencilClip) {
1253 GR_GL(StencilFunc(GL_EQUAL, clipStencilMask, clipStencilMask));
1254 } else {
1255 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1256 }
1257 GR_GL(StencilMask(pathStencilMask));
1258 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1259 GR_GL(StencilOp(GL_KEEP, GL_INVERT, GL_INVERT));
1260 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1261 if (!fSingleStencilPassForWinding) {
1262 GR_GL(Disable(GL_CULL_FACE));
1263 }
1264 break;
1265 case kEvenOddColor_StencilPass: {
1266 GR_GL(Enable(GL_STENCIL_TEST));
1267 GLint funcRef = 0;
1268 GLuint funcMask = pathStencilMask;
1269 if (stencilClip) {
1270 funcRef |= clipStencilMask;
1271 funcMask |= clipStencilMask;
1272 }
1273 if (!fCurrDrawState.fReverseFill) {
1274 funcRef |= pathStencilMask;
1275 }
1276 glStencilFunc(GL_EQUAL, funcRef, funcMask);
1277 glStencilMask(pathStencilMask);
1278 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1279 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1280 if (!fSingleStencilPassForWinding) {
1281 GR_GL(Disable(GL_CULL_FACE));
1282 }
1283 } break;
1284 case kWindingStencil1_StencilPass:
1285 GR_GL(Enable(GL_STENCIL_TEST));
1286 if (fHasStencilWrap) {
1287 if (stencilClip) {
1288 GR_GL(StencilFunc(GL_EQUAL,
1289 clipStencilMask,
1290 clipStencilMask));
1291 } else {
1292 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1293 }
1294 if (fSingleStencilPassForWinding) {
1295 GR_GL(StencilOpSeparate(GL_FRONT, GL_KEEP,
1296 GL_INCR_WRAP, GL_INCR_WRAP));
1297 GR_GL(StencilOpSeparate(GL_BACK, GL_KEEP,
1298 GL_DECR_WRAP, GL_DECR_WRAP));
1299 } else {
1300 GR_GL(StencilOp(GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP));
1301 GR_GL(Enable(GL_CULL_FACE));
1302 GR_GL(CullFace(GL_BACK));
1303 }
1304 } else {
1305 // If we don't have wrap then we use the Func to detect
1306 // values that would wrap (0 on decr and mask on incr). We
1307 // make the func fail on these values and use the sfail op
1308 // to effectively wrap by inverting.
1309 // This applies whether we are doing a two-pass (front faces
1310 // followed by back faces) or a single pass (separate func/op)
1311
1312 // Note that in the case where we are also using stencil to
1313 // clip this means we will write into the path bits in clipped
1314 // out pixels. We still apply the clip bit in the color pass
1315 // stencil func so we don't draw color outside the clip.
1316 // We also will clear the stencil bits in clipped pixels by
1317 // using zero in the sfail op with write mask set to the
1318 // path mask.
1319 GR_GL(Enable(GL_STENCIL_TEST));
1320 if (fSingleStencilPassForWinding) {
1321 GR_GL(StencilFuncSeparate(GL_FRONT,
1322 GL_NOTEQUAL,
1323 pathStencilMask,
1324 pathStencilMask));
1325 GR_GL(StencilFuncSeparate(GL_BACK,
1326 GL_NOTEQUAL,
1327 0x0,
1328 pathStencilMask));
1329 GR_GL(StencilOpSeparate(GL_FRONT, GL_INVERT,
1330 GL_INCR, GL_INCR));
1331 GR_GL(StencilOpSeparate(GL_BACK, GL_INVERT,
1332 GL_DECR, GL_DECR));
1333 } else {
1334 GR_GL(StencilFunc(GL_NOTEQUAL,
1335 pathStencilMask,
1336 pathStencilMask));
1337 GR_GL(StencilOp(GL_INVERT, GL_INCR, GL_INCR));
1338 GR_GL(Enable(GL_CULL_FACE));
1339 GR_GL(CullFace(GL_BACK));
1340 }
1341 }
1342 GR_GL(StencilMask(pathStencilMask));
1343 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1344 break;
1345 case kWindingStencil2_StencilPass:
1346 GrAssert(!fSingleStencilPassForWinding);
1347 GR_GL(Enable(GL_STENCIL_TEST));
1348 if (fHasStencilWrap) {
1349 if (stencilClip) {
1350 GR_GL(StencilFunc(GL_EQUAL,
1351 clipStencilMask,
1352 clipStencilMask));
1353 } else {
1354 GR_GL(StencilFunc(GL_ALWAYS, 0x0, 0x0));
1355 }
1356 GR_GL(StencilOp(GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP));
1357 } else {
1358 GR_GL(StencilFunc(GL_NOTEQUAL, 0x0, pathStencilMask));
1359 GR_GL(StencilOp(GL_INVERT, GL_DECR, GL_DECR));
1360 }
1361 GR_GL(StencilMask(pathStencilMask));
1362 GR_GL(Enable(GL_CULL_FACE));
1363 GR_GL(CullFace(GL_FRONT));
1364 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1365 break;
1366 case kWindingColor_StencilPass: {
1367 GR_GL(Enable(GL_STENCIL_TEST));
1368 GLint funcRef = 0;
1369 GLuint funcMask = pathStencilMask;
1370 GLenum funcFunc;
1371 if (stencilClip) {
1372 funcRef |= clipStencilMask;
1373 funcMask |= clipStencilMask;
1374 }
1375 if (fCurrDrawState.fReverseFill) {
1376 funcFunc = GL_EQUAL;
1377 } else {
1378 funcFunc = GL_LESS;
1379 }
1380 GR_GL(StencilFunc(funcFunc, funcRef, funcMask));
1381 GR_GL(StencilMask(pathStencilMask));
1382 // must zero in sfail because winding w/o wrap will write
1383 // path stencil bits in clipped out pixels
1384 GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
1385 GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1386 if (!fSingleStencilPassForWinding) {
1387 GR_GL(Disable(GL_CULL_FACE));
1388 }
1389 } break;
1390 case kSetClip_StencilPass:
1391 GR_GL(Enable(GL_STENCIL_TEST));
1392 GR_GL(StencilFunc(GL_ALWAYS, clipStencilMask, clipStencilMask));
1393 GR_GL(StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE));
1394 GR_GL(StencilMask(clipStencilMask));
1395 GR_GL(ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
1396 if (!fSingleStencilPassForWinding) {
1397 GR_GL(Disable(GL_CULL_FACE));
1398 }
1399 break;
1400 default:
1401 GrAssert(!"Unexpected stencil pass.");
1402 break;
1403
1404 }
1405 fHWDrawState.fStencilPass = fCurrDrawState.fStencilPass;
1406 fHWDrawState.fReverseFill = fCurrDrawState.fReverseFill;
1407 fWriteMaskChanged = false;
1408 fHWStencilClip = stencilClip;
1409 }
1410}
1411
1412void GrGpuGL::flushGLStateCommon(PrimitiveType type) {
1413
1414 bool usingTexture = VertexHasTexCoords(fGeometrySrc.fVertexLayout);
1415
1416 // bind texture and set sampler state
1417 if (usingTexture) {
1418 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTexture;
1419
1420 if (NULL != nextTexture) {
1421 // if we created a rt/tex and rendered to it without using a texture
1422 // and now we're texuring from the rt it will still be the last bound
1423 // texture, but it needs resolving. So keep this out of the last
1424 // != next check.
1425 resolveTextureRenderTarget(nextTexture);
1426
1427 if (fHWDrawState.fTexture != nextTexture) {
1428
1429 GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID()));
1430 #if GR_COLLECT_STATS
1431 ++fStats.fTextureChngCnt;
1432 #endif
1433 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1434 fHWDrawState.fTexture = nextTexture;
1435 }
1436 const GrSamplerState& lastSampler = nextTexture->samplerState();
1437 if (lastSampler.isFilter() != fCurrDrawState.fSamplerState.isFilter()) {
1438 GLenum filter = fCurrDrawState.fSamplerState.isFilter() ?
1439 GL_LINEAR :
1440 GL_NEAREST;
1441 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1442 filter));
1443 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1444 filter));
1445 }
1446 if (lastSampler.getWrapX() != fCurrDrawState.fSamplerState.getWrapX()) {
1447 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1448 GrGLTexture::gWrapMode2GLWrap[
1449 fCurrDrawState.fSamplerState.getWrapX()]));
1450 }
1451 if (lastSampler.getWrapY() != fCurrDrawState.fSamplerState.getWrapY()) {
1452 GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1453 GrGLTexture::gWrapMode2GLWrap[
1454 fCurrDrawState.fSamplerState.getWrapY()]));
1455 }
1456 nextTexture->setSamplerState(fCurrDrawState.fSamplerState);
1457 } else {
1458 GrAssert(!"Rendering with texture vert flag set but no texture");
1459 if (NULL != fHWDrawState.fTexture) {
1460 GR_GL(BindTexture(GL_TEXTURE_2D, 0));
1461 // GrPrintf("---- bindtexture 0\n");
1462 #if GR_COLLECT_STATS
1463 ++fStats.fTextureChngCnt;
1464 #endif
1465 fHWDrawState.fTexture = NULL;
1466 }
1467 }
1468 }
1469
1470 flushRenderTarget();
1471
1472 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1473 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1474 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
1475 GR_GL(Enable(GL_DITHER));
1476 } else {
1477 GR_GL(Disable(GL_DITHER));
1478 }
1479 }
1480
1481#if GR_GL_DESKTOP
1482 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1483 // smooth lines.
1484 if (fRenderTargetChanged ||
1485 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1486 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1487 GLint msaa = 0;
1488 // only perform query if we know MSAA is supported.
1489 // calling on non-MSAA target caused a crash in one environment,
1490 // though I don't think it should.
1491 if (!fAASamples[kHigh_AALevel]) {
1492 GR_GL(GetIntegerv(GL_SAMPLE_BUFFERS, &msaa));
1493 }
1494 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1495 if (msaa) {
1496 GR_GL(Enable(GL_MULTISAMPLE));
1497 } else {
1498 GR_GL(Enable(GL_LINE_SMOOTH));
1499 }
1500 } else {
1501 if (msaa) {
1502 GR_GL(Disable(GL_MULTISAMPLE));
1503 }
1504 GR_GL(Disable(GL_LINE_SMOOTH));
1505 }
1506 }
1507#endif
1508
1509 bool blendOff = canDisableBlend();
1510 if (fHWBlendDisabled != blendOff) {
1511 if (blendOff) {
1512 GR_GL(Disable(GL_BLEND));
1513 } else {
1514 GR_GL(Enable(GL_BLEND));
1515 }
1516 fHWBlendDisabled = blendOff;
1517 }
1518
1519 if (!blendOff) {
1520 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1521 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1522 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1523 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1524 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1525 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1526 }
1527 }
1528
1529 // check for circular rendering
1530 GrAssert(!usingTexture ||
1531 NULL == fCurrDrawState.fRenderTarget ||
1532 NULL == fCurrDrawState.fTexture ||
1533 fCurrDrawState.fTexture->asRenderTarget() != fCurrDrawState.fRenderTarget);
1534
1535 flushStencil();
1536
1537 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
1538}
1539
1540void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
1541 fHWGeometryState.fVertexBuffer = buffer;
1542}
1543
1544void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1545 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1546 buffer == fGeometrySrc.fVertexBuffer));
1547
1548 if (fHWGeometryState.fVertexBuffer == buffer) {
1549 // deleting bound buffer does implied bind to 0
1550 fHWGeometryState.fVertexBuffer = NULL;
1551 }
1552}
1553
1554void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1555 fGeometrySrc.fIndexBuffer = buffer;
1556}
1557
1558void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1559 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1560 buffer == fGeometrySrc.fIndexBuffer));
1561
1562 if (fHWGeometryState.fIndexBuffer == buffer) {
1563 // deleting bound buffer does implied bind to 0
1564 fHWGeometryState.fIndexBuffer = NULL;
1565 }
1566}
1567
1568void GrGpuGL::notifyTextureBind(GrGLTexture* texture) {
1569 fHWDrawState.fTexture = texture;
1570#if GR_COLLECT_STATS
1571 ++fStats.fTextureChngCnt;
1572#endif
1573}
1574
1575void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1576 GrAssert(NULL != renderTarget);
1577
1578 // if the bound FBO is destroyed we can't rely on the implicit bind to 0
1579 // a) we want the default RT which may not be FBO 0
1580 // b) we set more state than just FBO based on the RT
1581 // So trash the HW state to force an RT flush next time
1582 if (fCurrDrawState.fRenderTarget == renderTarget) {
1583 fCurrDrawState.fRenderTarget = (GrRenderTarget*)&fDefaultRenderTarget;
1584 }
1585 if (fHWDrawState.fRenderTarget == renderTarget) {
1586 fHWDrawState.fRenderTarget = NULL;
1587 }
1588 if (fClipState.fStencilClipTarget == renderTarget) {
1589 fClipState.fStencilClipTarget = NULL;
1590 }
1591}
1592
1593void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
1594 if (fCurrDrawState.fTexture == texture) {
1595 fCurrDrawState.fTexture = NULL;
1596 }
1597 if (fHWDrawState.fTexture == texture) {
1598 // deleting bound texture does implied bind to 0
1599 fHWDrawState.fTexture = NULL;
1600 }
1601}
1602
1603void GrGpuGL::notifyTextureRemoveRenderTarget(GrGLTexture* texture) {
1604 GrAssert(NULL != texture->asRenderTarget());
1605
1606 // if there is a pending resolve, perform it.
1607 resolveTextureRenderTarget(texture);
1608}
1609
1610bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
1611 GLenum* internalFormat,
1612 GLenum* format,
1613 GLenum* type) {
1614 switch (config) {
1615 case GrTexture::kRGBA_8888_PixelConfig:
1616 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
1617 *format = SK_GL_32BPP_COLOR_FORMAT;
1618 *internalFormat = GL_RGBA;
1619 *type = GL_UNSIGNED_BYTE;
1620 break;
1621 case GrTexture::kRGB_565_PixelConfig:
1622 *format = GL_RGB;
1623 *internalFormat = GL_RGB;
1624 *type = GL_UNSIGNED_SHORT_5_6_5;
1625 break;
1626 case GrTexture::kRGBA_4444_PixelConfig:
1627 *format = GL_RGBA;
1628 *internalFormat = GL_RGBA;
1629 *type = GL_UNSIGNED_SHORT_4_4_4_4;
1630 break;
1631 case GrTexture::kIndex_8_PixelConfig:
1632 if (this->supports8BitPalette()) {
1633 *format = GR_PALETTE8_RGBA8;
1634 *internalFormat = GR_PALETTE8_RGBA8;
1635 *type = GL_UNSIGNED_BYTE; // unused I think
1636 } else {
1637 return false;
1638 }
1639 break;
1640 case GrTexture::kAlpha_8_PixelConfig:
1641 *format = GL_ALPHA;
1642 *internalFormat = GL_ALPHA;
1643 *type = GL_UNSIGNED_BYTE;
1644 break;
1645 default:
1646 return false;
1647 }
1648 return true;
1649}
1650
1651/* On ES the internalFormat and format must match for TexImage and we use
1652 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1653 decide the internalFormat. However, on ES internalFormat for
1654 RenderBufferStorage* has to be a specific format (not a base format like
1655 GL_RGBA).
1656 */
1657bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) {
1658 switch (config) {
1659 case GrTexture::kRGBA_8888_PixelConfig:
1660 case GrTexture::kRGBX_8888_PixelConfig:
1661 if (fRGBA8Renderbuffer) {
1662 *format = GR_RGBA8;
1663 return true;
1664 } else {
1665 return false;
1666 }
1667#if GR_GL_ES // ES2 supports 565. ES1 supports it with FBO extension
1668 // desktop GL has no such internal format
1669 case GrTexture::kRGB_565_PixelConfig:
1670 *format = GR_RGB565;
1671 return true;
1672#endif
1673 case GrTexture::kRGBA_4444_PixelConfig:
1674 *format = GL_RGBA4;
1675 return true;
1676 default:
1677 return false;
1678 }
1679}
1680
1681///////////////////////////////////////////////////////////////////////////////
1682
1683void GrGLCheckErr(const char* location, const char* call) {
1684 uint32_t err = glGetError();
1685 if (GL_NO_ERROR != err) {
1686 GrPrintf("---- glGetError %x", err);
1687 if (NULL != location) {
1688 GrPrintf(" at\n\t%s", location);
1689 }
1690 if (NULL != call) {
1691 GrPrintf("\n\t\t%s", call);
1692 }
1693 GrPrintf("\n");
1694 }
1695}
1696
1697///////////////////////////////////////////////////////////////////////////////
1698
1699typedef void (*glProc)(void);
1700
1701void get_gl_proc(const char procName[], glProc *address) {
1702#if GR_WIN32_BUILD
1703 *address = wglGetProcAddress(procName);
1704 GrAssert(NULL != *address);
1705#elif GR_MAC_BUILD || GR_IOS_BUILD
1706 GrAssert(!"Extensions don't need to be initialized!");
1707#elif GR_ANDROID_BUILD
1708 *address = eglGetProcAddress(procName);
1709 GrAssert(NULL != *address);
1710#elif GR_LINUX_BUILD
1711 GR_STATIC_ASSERT(!"Add environment-dependent implementation here");
1712 //*address = glXGetProcAddressARB(procName);
1713 //*address = eglGetProcAddress(procName);
1714#elif GR_QNX_BUILD
1715 *address = eglGetProcAddress(procName);
1716 GrAssert(NULL != *address);
1717#else
1718 // hopefully we're on a system with EGL
1719 *address = eglGetProcAddress(procName);
1720 GrAssert(NULL != *address);
1721#endif
1722}
1723
1724#define GET_PROC(EXT_STRUCT, PROC_NAME, EXT_TAG) \
1725 get_gl_proc("gl" #PROC_NAME #EXT_TAG, (glProc*)&EXT_STRUCT-> PROC_NAME);
1726
1727extern void GrGLInitExtensions(GrGLExts* exts) {
1728 exts->GenFramebuffers = NULL;
1729 exts->BindFramebuffer = NULL;
1730 exts->FramebufferTexture2D = NULL;
1731 exts->CheckFramebufferStatus = NULL;
1732 exts->DeleteFramebuffers = NULL;
1733 exts->RenderbufferStorage = NULL;
1734 exts->GenRenderbuffers = NULL;
1735 exts->DeleteRenderbuffers = NULL;
1736 exts->FramebufferRenderbuffer = NULL;
1737 exts->BindRenderbuffer = NULL;
1738 exts->RenderbufferStorageMultisample = NULL;
1739 exts->BlitFramebuffer = NULL;
1740 exts->ResolveMultisampleFramebuffer = NULL;
1741 exts->FramebufferTexture2DMultisample = NULL;
1742 exts->MapBuffer = NULL;
1743 exts->UnmapBuffer = NULL;
1744
1745#if GR_MAC_BUILD
1746 exts->GenFramebuffers = glGenFramebuffers;
1747 exts->BindFramebuffer = glBindFramebuffer;
1748 exts->FramebufferTexture2D = glFramebufferTexture2D;
1749 exts->CheckFramebufferStatus = glCheckFramebufferStatus;
1750 exts->DeleteFramebuffers = glDeleteFramebuffers;
1751 exts->RenderbufferStorage = glRenderbufferStorage;
1752 exts->GenRenderbuffers = glGenRenderbuffers;
1753 exts->DeleteRenderbuffers = glDeleteRenderbuffers;
1754 exts->FramebufferRenderbuffer = glFramebufferRenderbuffer;
1755 exts->BindRenderbuffer = glBindRenderbuffer;
1756 exts->RenderbufferStorageMultisample = glRenderbufferStorageMultisample;
1757 exts->BlitFramebuffer = glBlitFramebuffer;
1758 exts->MapBuffer = glMapBuffer;
1759 exts->UnmapBuffer = glUnmapBuffer;
1760#elif GR_IOS_BUILD
1761 exts->GenFramebuffers = glGenFramebuffers;
1762 exts->BindFramebuffer = glBindFramebuffer;
1763 exts->FramebufferTexture2D = glFramebufferTexture2D;
1764 exts->CheckFramebufferStatus = glCheckFramebufferStatus;
1765 exts->DeleteFramebuffers = glDeleteFramebuffers;
1766 exts->RenderbufferStorage = glRenderbufferStorage;
1767 exts->GenRenderbuffers = glGenRenderbuffers;
1768 exts->DeleteRenderbuffers = glDeleteRenderbuffers;
1769 exts->FramebufferRenderbuffer = glFramebufferRenderbuffer;
1770 exts->BindRenderbuffer = glBindRenderbuffer;
1771 exts->RenderbufferStorageMultisample = glRenderbufferStorageMultisampleAPPLE;
1772 exts->ResolveMultisampleFramebuffer = glResolveMultisampleFramebufferAPPLE;
1773 exts->MapBuffer = glMapBufferOES;
1774 exts->UnmapBuffer = glUnmapBufferOES;
1775#else
1776 GLint major, minor;
1777 gl_version(&major, &minor);
1778 #if GR_GL_DESKTOP
1779 if (major >= 3) {// FBO, FBOMS, and FBOBLIT part of 3.0
1780 exts->GenFramebuffers = glGenFramebuffers;
1781 exts->BindFramebuffer = glBindFramebuffer;
1782 exts->FramebufferTexture2D = glFramebufferTexture2D;
1783 exts->CheckFramebufferStatus = glCheckFramebufferStatus;
1784 exts->DeleteFramebuffers = glDeleteFramebuffers;
1785 exts->RenderbufferStorage = glRenderbufferStorage;
1786 exts->GenRenderbuffers = glGenRenderbuffers;
1787 exts->DeleteRenderbuffers = glDeleteRenderbuffers;
1788 exts->FramebufferRenderbuffer = glFramebufferRenderbuffer;
1789 exts->BindRenderbuffer = glBindRenderbuffer;
1790 exts->RenderbufferStorageMultisample = glRenderbufferStorageMultisample;
1791 exts->BlitFramebuffer = glBlitFramebuffer;
1792 } else if (has_gl_extension("GL_ARB_framebuffer_object")) {
1793 GET_PROC(exts, GenFramebuffers, ARB);
1794 GET_PROC(exts, BindFramebuffer, ARB);
1795 GET_PROC(exts, FramebufferTexture2D, ARB);
1796 GET_PROC(exts, CheckFramebufferStatus, ARB);
1797 GET_PROC(exts, DeleteFramebuffers, ARB);
1798 GET_PROC(exts, RenderbufferStorage, ARB);
1799 GET_PROC(exts, GenRenderbuffers, ARB);
1800 GET_PROC(exts, DeleteRenderbuffers, ARB);
1801 GET_PROC(exts, FramebufferRenderbuffer, ARB);
1802 GET_PROC(exts, BindRenderbuffer, ARB);
1803 GET_PROC(exts, RenderbufferStorageMultisample, ARB);
1804 GET_PROC(exts, BlitFramebuffer, ARB);
1805 } else {
1806 // we require some form of FBO
1807 GrAssert(has_gl_extension("GL_EXT_framebuffer_object"));
1808 GET_PROC(exts, GenFramebuffers, EXT);
1809 GET_PROC(exts, BindFramebuffer, EXT);
1810 GET_PROC(exts, FramebufferTexture2D, EXT);
1811 GET_PROC(exts, CheckFramebufferStatus, EXT);
1812 GET_PROC(exts, DeleteFramebuffers, EXT);
1813 GET_PROC(exts, RenderbufferStorage, EXT);
1814 GET_PROC(exts, GenRenderbuffers, EXT);
1815 GET_PROC(exts, DeleteRenderbuffers, EXT);
1816 GET_PROC(exts, FramebufferRenderbuffer, EXT);
1817 GET_PROC(exts, BindRenderbuffer, EXT);
1818 if (has_gl_extension("GL_EXT_framebuffer_multisample")) {
1819 GET_PROC(exts, RenderbufferStorageMultisample, EXT);
1820 }
1821 if (has_gl_extension("GL_EXT_framebuffer_blit")) {
1822 GET_PROC(exts, BlitFramebuffer, EXT);
1823 }
1824 }
1825 // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
1826 exts->MapBuffer = glMapBuffer;
1827 exts->UnmapBuffer = glUnmapBuffer;
1828 #else // !GR_GL_DESKTOP
1829 if (major >= 2) {// ES 2.0 supports FBO
1830 exts->GenFramebuffers = glGenFramebuffers;
1831 exts->BindFramebuffer = glBindFramebuffer;
1832 exts->FramebufferTexture2D = glFramebufferTexture2D;
1833 exts->CheckFramebufferStatus = glCheckFramebufferStatus;
1834 exts->DeleteFramebuffers = glDeleteFramebuffers;
1835 exts->RenderbufferStorage = glRenderbufferStorage;
1836 exts->GenRenderbuffers = glGenRenderbuffers;
1837 exts->DeleteRenderbuffers = glDeleteRenderbuffers;
1838 exts->FramebufferRenderbuffer = glFramebufferRenderbuffer;
1839 exts->BindRenderbuffer = glBindRenderbuffer;
1840 } else {
1841 // we require some form of FBO
1842 GrAssert(has_gl_extension("GL_OES_framebuffer_object"));
1843
1844 GET_PROC(exts, GenFramebuffers, OES);
1845 GET_PROC(exts, BindFramebuffer, OES);
1846 GET_PROC(exts, FramebufferTexture2D, OES);
1847 GET_PROC(exts, CheckFramebufferStatus, OES);
1848 GET_PROC(exts, DeleteFramebuffers, OES);
1849 GET_PROC(exts, RenderbufferStorage, OES);
1850 GET_PROC(exts, GenRenderbuffers, OES);
1851 GET_PROC(exts, DeleteRenderbuffers, OES);
1852 GET_PROC(exts, FramebufferRenderbuffer, OES);
1853 GET_PROC(exts, BindRenderbuffer, OES);
1854 }
1855 if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
1856 GET_PROC(exts, ResolveMultisampleFramebuffer, APPLE);
1857 }
1858 if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
1859 GET_PROC(exts, FramebufferTexture2DMultisample, IMG);
1860 }
1861 if (has_gl_extension("GL_OES_mapbuffer")) {
1862 GET_PROC(exts, MapBuffer, OES);
1863 GET_PROC(exts, UnmapBuffer, OES);
1864 }
1865 #endif // !GR_GL_DESKTOP
1866#endif // BUILD
1867}
1868
1869bool gPrintGL = true;
1870