1 /*
2 Copyright 2011 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 "GrTypes.h"
20
21 static const GrGLuint GR_MAX_GLUINT = ~0;
22 static const GrGLint GR_INVAL_GLINT = ~0;
23
24 // we use a spare texture unit to avoid
25 // mucking with the state of any of the stages.
26 static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
27
28 #define SKIP_CACHE_CHECK true
29
30 static const GrGLenum gXfermodeCoeff2Blend[] = {
31 GR_GL_ZERO,
32 GR_GL_ONE,
33 GR_GL_SRC_COLOR,
34 GR_GL_ONE_MINUS_SRC_COLOR,
35 GR_GL_DST_COLOR,
36 GR_GL_ONE_MINUS_DST_COLOR,
37 GR_GL_SRC_ALPHA,
38 GR_GL_ONE_MINUS_SRC_ALPHA,
39 GR_GL_DST_ALPHA,
40 GR_GL_ONE_MINUS_DST_ALPHA,
41 GR_GL_CONSTANT_COLOR,
42 GR_GL_ONE_MINUS_CONSTANT_COLOR,
43 GR_GL_CONSTANT_ALPHA,
44 GR_GL_ONE_MINUS_CONSTANT_ALPHA,
45
46 // extended blend coeffs
47 GR_GL_SRC1_COLOR,
48 GR_GL_ONE_MINUS_SRC1_COLOR,
49 GR_GL_SRC1_ALPHA,
50 GR_GL_ONE_MINUS_SRC1_ALPHA,
51 };
52
BlendCoeffReferencesConstant(GrBlendCoeff coeff)53 bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
54 static const bool gCoeffReferencesBlendConst[] = {
55 false,
56 false,
57 false,
58 false,
59 false,
60 false,
61 false,
62 false,
63 false,
64 false,
65 true,
66 true,
67 true,
68 true,
69
70 // extended blend coeffs
71 false,
72 false,
73 false,
74 false,
75 };
76 return gCoeffReferencesBlendConst[coeff];
77 GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
78
79 GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
80 GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
81 GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
82 GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
83 GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
84 GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
85 GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
86 GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
87 GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
88 GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
89 GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
90 GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
91 GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
92 GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
93
94 GR_STATIC_ASSERT(14 == kS2C_BlendCoeff);
95 GR_STATIC_ASSERT(15 == kIS2C_BlendCoeff);
96 GR_STATIC_ASSERT(16 == kS2A_BlendCoeff);
97 GR_STATIC_ASSERT(17 == kIS2A_BlendCoeff);
98
99 // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
100 GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
101 }
102
103 ///////////////////////////////////////////////////////////////////////////////
104
AdjustTextureMatrix(const GrGLTexture * texture,GrSamplerState::SampleMode mode,GrMatrix * matrix)105 void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
106 GrSamplerState::SampleMode mode,
107 GrMatrix* matrix) {
108 GrAssert(NULL != texture);
109 GrAssert(NULL != matrix);
110 if (GR_Scalar1 != texture->contentScaleX() ||
111 GR_Scalar1 != texture->contentScaleY()) {
112 if (GrSamplerState::kRadial_SampleMode == mode) {
113 GrMatrix scale;
114 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
115 matrix->postConcat(scale);
116 } else if (GrSamplerState::kNormal_SampleMode == mode) {
117 GrMatrix scale;
118 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
119 matrix->postConcat(scale);
120 } else {
121 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
122 }
123 }
124 GrGLTexture::Orientation orientation = texture->orientation();
125 if (GrGLTexture::kBottomUp_Orientation == orientation) {
126 GrMatrix invY;
127 invY.setAll(GR_Scalar1, 0, 0,
128 0, -GR_Scalar1, GR_Scalar1,
129 0, 0, GrMatrix::I()[8]);
130 matrix->postConcat(invY);
131 } else {
132 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
133 }
134 }
135
TextureMatrixIsIdentity(const GrGLTexture * texture,const GrSamplerState & sampler)136 bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
137 const GrSamplerState& sampler) {
138 GrAssert(NULL != texture);
139 if (!sampler.getMatrix().isIdentity()) {
140 return false;
141 }
142 if (GR_Scalar1 != texture->contentScaleX() ||
143 GR_Scalar1 != texture->contentScaleY()) {
144 return false;
145 }
146 GrGLTexture::Orientation orientation = texture->orientation();
147 if (GrGLTexture::kBottomUp_Orientation == orientation) {
148 return false;
149 } else {
150 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
151 }
152 return true;
153 }
154
155 ///////////////////////////////////////////////////////////////////////////////
156
157 static bool gPrintStartupSpew;
158
fbo_test(int w,int h)159 static bool fbo_test(int w, int h) {
160
161 GrGLint savedFBO;
162 GrGLint savedTexUnit;
163 GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
164 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
165
166 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
167
168 GrGLuint testFBO;
169 GR_GL(GenFramebuffers(1, &testFBO));
170 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
171 GrGLuint testRTTex;
172 GR_GL(GenTextures(1, &testRTTex));
173 GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
174 // some implementations require texture to be mip-map complete before
175 // FBO with level 0 bound as color attachment will be framebuffer complete.
176 GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
177 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
178 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
179 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
180 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
181 GR_GL_TEXTURE_2D, testRTTex, 0));
182 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
183 GR_GL(DeleteFramebuffers(1, &testFBO));
184 GR_GL(DeleteTextures(1, &testRTTex));
185
186 GR_GL(ActiveTexture(savedTexUnit));
187 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
188
189 return status == GR_GL_FRAMEBUFFER_COMPLETE;
190 }
191
GrGpuGL()192 GrGpuGL::GrGpuGL() {
193
194 if (gPrintStartupSpew) {
195 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
196 this);
197 GrPrintf("------ VENDOR %s\n",
198 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
199 GrPrintf("------ RENDERER %s\n",
200 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
201 GrPrintf("------ VERSION %s\n",
202 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
203 GrPrintf("------ EXTENSIONS\n %s \n",
204 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
205 }
206
207 GrGLClearErr();
208
209 resetDirtyFlags();
210
211 GrGLint maxTextureUnits;
212 // check FS and fixed-function texture unit limits
213 // we only use textures in the fragment stage currently.
214 // checks are > to make sure we have a spare unit.
215 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
216 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
217 GrAssert(maxTextureUnits > kNumStages);
218 }
219 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
220 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
221 GrAssert(maxTextureUnits > kNumStages);
222 }
223 if (GR_GL_SUPPORT_ES2) {
224 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
225 &fMaxFragmentUniformVectors);
226 } else if (GR_GL_SUPPORT_DESKTOP) {
227 GrGLint max;
228 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
229 fMaxFragmentUniformVectors = max / 4;
230 } else {
231 fMaxFragmentUniformVectors = 16;
232 }
233
234 ////////////////////////////////////////////////////////////////////////////
235 // Check for supported features.
236
237 int major, minor;
238 gl_version(&major, &minor);
239
240 GrGLint numFormats;
241 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
242 GrAutoSTMalloc<10, GrGLint> formats(numFormats);
243 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
244 for (int i = 0; i < numFormats; ++i) {
245 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
246 f8bitPaletteSupport = true;
247 break;
248 }
249 }
250
251 if (gPrintStartupSpew) {
252 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
253 }
254
255 GR_STATIC_ASSERT(0 == kNone_GrAALevel);
256 GR_STATIC_ASSERT(1 == kLow_GrAALevel);
257 GR_STATIC_ASSERT(2 == kMed_GrAALevel);
258 GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
259
260 memset(fAASamples, 0, sizeof(fAASamples));
261 fMSFBOType = kNone_MSFBO;
262 if (GR_GL_SUPPORT_ES) {
263 if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
264 // chrome's extension is equivalent to the EXT msaa
265 // and fbo_blit extensions.
266 fMSFBOType = kDesktopEXT_MSFBO;
267 } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
268 fMSFBOType = kAppleES_MSFBO;
269 }
270 } else {
271 GrAssert(GR_GL_SUPPORT_DESKTOP);
272 if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
273 fMSFBOType = kDesktopARB_MSFBO;
274 } else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
275 has_gl_extension("GL_EXT_framebuffer_blit")) {
276 fMSFBOType = kDesktopEXT_MSFBO;
277 }
278 }
279 if (gPrintStartupSpew) {
280 switch (fMSFBOType) {
281 case kNone_MSFBO:
282 GrPrintf("MSAA Support: NONE\n");
283 break;
284 case kDesktopARB_MSFBO:
285 GrPrintf("MSAA Support: DESKTOP ARB.\n");
286 break;
287 case kDesktopEXT_MSFBO:
288 GrPrintf("MSAA Support: DESKTOP EXT.\n");
289 break;
290 case kAppleES_MSFBO:
291 GrPrintf("MSAA Support: APPLE ES.\n");
292 break;
293 }
294 }
295
296 if (kNone_MSFBO != fMSFBOType) {
297 GrGLint maxSamples;
298 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
299 if (maxSamples > 1 ) {
300 fAASamples[kNone_GrAALevel] = 0;
301 fAASamples[kLow_GrAALevel] = GrMax(2,
302 GrFixedFloorToInt((GR_FixedHalf) *
303 maxSamples));
304 fAASamples[kMed_GrAALevel] = GrMax(2,
305 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
306 maxSamples));
307 fAASamples[kHigh_GrAALevel] = maxSamples;
308 }
309 if (gPrintStartupSpew) {
310 GrPrintf("\tMax Samples: %d\n", maxSamples);
311 }
312 }
313 fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
314
315 if (GR_GL_SUPPORT_DESKTOP) {
316 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
317 has_gl_extension("GL_EXT_stencil_wrap");
318 } else {
319 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
320 }
321 if (gPrintStartupSpew) {
322 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
323 }
324
325 if (GR_GL_SUPPORT_DESKTOP) {
326 // we could also look for GL_ATI_separate_stencil extension or
327 // GL_EXT_stencil_two_side but they use different function signatures
328 // than GL2.0+ (and than each other).
329 fTwoSidedStencilSupport = (major >= 2);
330 // supported on GL 1.4 and higher or by extension
331 fStencilWrapOpsSupport = (major > 1) ||
332 ((1 == major) && (minor >= 4)) ||
333 has_gl_extension("GL_EXT_stencil_wrap");
334 } else {
335 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
336 // an ES1 extension.
337 fTwoSidedStencilSupport = (major >= 2);
338 // stencil wrap support is in ES2, ES1 requires extension.
339 fStencilWrapOpsSupport = (major > 1) ||
340 has_gl_extension("GL_OES_stencil_wrap");
341 }
342 if (gPrintStartupSpew) {
343 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
344 (fTwoSidedStencilSupport ? "YES" : "NO"),
345 (fStencilWrapOpsSupport ? "YES" : "NO"));
346 }
347
348 if (GR_GL_SUPPORT_DESKTOP) {
349 fRGBA8Renderbuffer = true;
350 } else {
351 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
352 }
353 if (gPrintStartupSpew) {
354 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
355 }
356
357
358 if (GR_GL_SUPPORT_ES) {
359 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
360 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
361 }
362 }
363
364 if (GR_GL_SUPPORT_DESKTOP) {
365 fBufferLockSupport = true; // we require VBO support and the desktop VBO
366 // extension includes glMapBuffer.
367 } else {
368 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
369 }
370
371 if (gPrintStartupSpew) {
372 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
373 }
374
375 if (GR_GL_SUPPORT_DESKTOP) {
376 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
377 fNPOTTextureTileSupport = true;
378 fNPOTTextureSupport = true;
379 } else {
380 fNPOTTextureTileSupport = false;
381 fNPOTTextureSupport = false;
382 }
383 } else {
384 if (major >= 2) {
385 fNPOTTextureSupport = true;
386 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
387 } else {
388 fNPOTTextureSupport =
389 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
390 fNPOTTextureTileSupport = false;
391 }
392 }
393
394 fAALineSupport = GR_GL_SUPPORT_DESKTOP;
395
396 ////////////////////////////////////////////////////////////////////////////
397 // Experiments to determine limitations that can't be queried. TODO: Make
398 // these a preprocess that generate some compile time constants.
399
400 // sanity check to make sure we can at least create an FBO from a POT texture
401
402 bool simpleFBOSuccess = fbo_test(128, 128);
403 if (gPrintStartupSpew) {
404 if (!simpleFBOSuccess) {
405 GrPrintf("FBO Sanity Test: FAILED\n");
406 } else {
407 GrPrintf("FBO Sanity Test: PASSED\n");
408 }
409 }
410 GrAssert(simpleFBOSuccess);
411
412 /* Experimentation has found that some GLs that support NPOT textures
413 do not support FBOs with a NPOT texture. They report "unsupported" FBO
414 status. I don't know how to explicitly query for this. Do an
415 experiment. Note they may support NPOT with a renderbuffer but not a
416 texture. Presumably, the implementation bloats the renderbuffer
417 internally to the next POT.
418 */
419 bool fNPOTRenderTargetSupport = false;
420 if (fNPOTTextureSupport) {
421 fNPOTRenderTargetSupport = fbo_test(200, 200);
422 }
423
424 if (gPrintStartupSpew) {
425 if (fNPOTTextureSupport) {
426 GrPrintf("NPOT textures supported\n");
427 if (fNPOTTextureTileSupport) {
428 GrPrintf("NPOT texture tiling supported\n");
429 } else {
430 GrPrintf("NPOT texture tiling NOT supported\n");
431 }
432 if (fNPOTRenderTargetSupport) {
433 GrPrintf("NPOT render targets supported\n");
434 } else {
435 GrPrintf("NPOT render targets NOT supported\n");
436 }
437 } else {
438 GrPrintf("NPOT textures NOT supported\n");
439 }
440 }
441
442 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
443
444 /* The iPhone 4 has a restriction that for an FBO with texture color
445 attachment with height <= 8 then the width must be <= height. Here
446 we look for such a limitation.
447 */
448 fMinRenderTargetHeight = GR_INVAL_GLINT;
449 GrGLint maxRenderSize;
450 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
451 // fbo_test creates FBOs with texture bound to the color attachment
452 maxRenderSize = GrMin(maxRenderSize, fMaxTextureDimension);
453
454 if (gPrintStartupSpew) {
455 GrPrintf("Small height FBO texture experiments\n");
456 }
457
458 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
459 GrGLuint w = maxRenderSize;
460 GrGLuint h = i;
461 if (fbo_test(w, h)) {
462 if (gPrintStartupSpew) {
463 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
464 }
465 fMinRenderTargetHeight = i;
466 break;
467 } else {
468 if (gPrintStartupSpew) {
469 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
470 }
471 }
472 }
473 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
474
475 if (gPrintStartupSpew) {
476 GrPrintf("Small width FBO texture experiments\n");
477 }
478 fMinRenderTargetWidth = GR_MAX_GLUINT;
479 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
480 GrGLuint w = i;
481 GrGLuint h = maxRenderSize;
482 if (fbo_test(w, h)) {
483 if (gPrintStartupSpew) {
484 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
485 }
486 fMinRenderTargetWidth = i;
487 break;
488 } else {
489 if (gPrintStartupSpew) {
490 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
491 }
492 }
493 }
494 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
495 }
496
~GrGpuGL()497 GrGpuGL::~GrGpuGL() {
498 }
499
resetContext()500 void GrGpuGL::resetContext() {
501 // We detect cases when blending is effectively off
502 fHWBlendDisabled = false;
503 GR_GL(Enable(GR_GL_BLEND));
504
505 // we don't use the zb at all
506 GR_GL(Disable(GR_GL_DEPTH_TEST));
507 GR_GL(DepthMask(GR_GL_FALSE));
508
509 GR_GL(Disable(GR_GL_CULL_FACE));
510 GR_GL(FrontFace(GR_GL_CCW));
511 fHWDrawState.fDrawFace = kBoth_DrawFace;
512
513 GR_GL(Disable(GR_GL_DITHER));
514 if (GR_GL_SUPPORT_DESKTOP) {
515 GR_GL(Disable(GR_GL_LINE_SMOOTH));
516 GR_GL(Disable(GR_GL_POINT_SMOOTH));
517 GR_GL(Disable(GR_GL_MULTISAMPLE));
518 fHWAAState.fMSAAEnabled = false;
519 fHWAAState.fSmoothLineEnabled = false;
520 }
521
522 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
523 fHWDrawState.fFlagBits = 0;
524
525 // we only ever use lines in hairline mode
526 GR_GL(LineWidth(1));
527
528 // invalid
529 fActiveTextureUnitIdx = -1;
530
531 // illegal values
532 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
533 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
534
535 fHWDrawState.fBlendConstant = 0x00000000;
536 GR_GL(BlendColor(0,0,0,0));
537
538 fHWDrawState.fColor = GrColor_ILLEGAL;
539
540 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
541
542 for (int s = 0; s < kNumStages; ++s) {
543 fHWDrawState.fTextures[s] = NULL;
544 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
545 -GR_ScalarMax,
546 true);
547
548 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
549 }
550
551 fHWBounds.fScissorRect.invalidate();
552 fHWBounds.fScissorEnabled = false;
553 GR_GL(Disable(GR_GL_SCISSOR_TEST));
554 fHWBounds.fViewportRect.invalidate();
555
556 fHWDrawState.fStencilSettings.invalidate();
557 fHWStencilClip = false;
558 fClipState.fClipIsDirty = true;
559
560 fHWGeometryState.fIndexBuffer = NULL;
561 fHWGeometryState.fVertexBuffer = NULL;
562
563 fHWGeometryState.fArrayPtrsDirty = true;
564
565 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
566 fHWDrawState.fRenderTarget = NULL;
567 }
568
onCreatePlatformSurface(const GrPlatformSurfaceDesc & desc)569 GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
570
571 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
572 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
573 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
574 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
575
576 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
577 if (isRenderTarget) {
578 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
579 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
580 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
581 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
582 } else {
583 GrAssert(!isTexture); // this should have been filtered by GrContext
584 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
585 }
586 } else {
587 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
588 }
589 // we don't know what the RB ids are without glGets and we don't care
590 // since we aren't responsible for deleting them.
591 rtIDs.fStencilRenderbufferID = 0;
592 rtIDs.fMSColorRenderbufferID = 0;
593
594 rtIDs.fOwnIDs = false;
595 } else {
596 rtIDs.reset();
597 }
598
599 if (isTexture) {
600 GrGLTexture::GLTextureDesc texDesc;
601 GrGLenum dontCare;
602 if (!canBeTexture(desc.fConfig, &dontCare,
603 &texDesc.fUploadFormat,
604 &texDesc.fUploadType)) {
605 return NULL;
606 }
607
608 GrGLTexture::TexParams params;
609
610 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
611 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
612
613 texDesc.fFormat = texDesc.fFormat;
614 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
615 texDesc.fStencilBits = desc.fStencilBits;
616 texDesc.fTextureID = desc.fPlatformTexture;
617 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
618 texDesc.fOwnsID = false;
619
620 params.invalidate(); // rather than do glGets.
621
622 return new GrGLTexture(this, texDesc, rtIDs, params);
623 } else {
624 GrGLIRect viewport;
625 viewport.fLeft = 0;
626 viewport.fBottom = 0;
627 viewport.fWidth = desc.fWidth;
628 viewport.fHeight = desc.fHeight;
629
630 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
631 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
632 viewport, NULL);
633 }
634 }
635
onCreateRenderTargetFrom3DApiState()636 GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
637
638 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
639
640 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
641 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
642 rtIDs.fMSColorRenderbufferID = 0;
643 rtIDs.fStencilRenderbufferID = 0;
644
645 GrGLIRect viewport;
646 viewport.setFromGLViewport();
647 GrGLuint stencilBits;
648 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
649
650 GrGLint samples;
651 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
652
653 rtIDs.fOwnIDs = false;
654
655 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
656 (samples > 0), viewport, NULL);
657 }
658
659 ///////////////////////////////////////////////////////////////////////////////
660
661 static const GrGLuint UNKNOWN_BITS = ~0;
662
663 struct StencilFormat {
664 GrGLenum fEnum;
665 GrGLuint fBits;
666 bool fPacked;
667 };
668
GrGLStencilFormats()669 const StencilFormat* GrGLStencilFormats() {
670 // defines stencil formats from more to less preferred
671 static const StencilFormat desktopStencilFormats[] = {
672 {GR_GL_STENCIL_INDEX8, 8, false},
673 {GR_GL_STENCIL_INDEX16, 16, false},
674 {GR_GL_DEPTH24_STENCIL8, 8, true },
675 {GR_GL_STENCIL_INDEX4, 4, false},
676 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
677 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
678 {0, 0, false}
679 };
680
681 static const StencilFormat esStencilFormats[] = {
682 {GR_GL_STENCIL_INDEX8, 8, false},
683 {GR_GL_DEPTH24_STENCIL8, 8, true },
684 {GR_GL_STENCIL_INDEX4, 4, false},
685 {0, 0, false}
686 };
687
688 if (GR_GL_SUPPORT_DESKTOP) {
689 return desktopStencilFormats;
690 } else {
691 return esStencilFormats;
692 }
693 }
694
695 // good to set a break-point here to know when createTexture fails
return_null_texture()696 static GrTexture* return_null_texture() {
697 // GrAssert(!"null texture");
698 return NULL;
699 }
700
701 #if GR_DEBUG
as_size_t(int x)702 static size_t as_size_t(int x) {
703 return x;
704 }
705 #endif
706
onCreateTexture(const GrTextureDesc & desc,const void * srcData,size_t rowBytes)707 GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
708 const void* srcData,
709 size_t rowBytes) {
710
711 #if GR_COLLECT_STATS
712 ++fStats.fTextureCreateCnt;
713 #endif
714
715 this->setSpareTextureUnit();
716
717 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
718 GR_GL_NEAREST,
719 GR_GL_CLAMP_TO_EDGE,
720 GR_GL_CLAMP_TO_EDGE
721 };
722
723 GrGLTexture::GLTextureDesc glDesc;
724 GrGLenum internalFormat;
725
726 glDesc.fContentWidth = desc.fWidth;
727 glDesc.fContentHeight = desc.fHeight;
728 glDesc.fAllocWidth = desc.fWidth;
729 glDesc.fAllocHeight = desc.fHeight;
730 glDesc.fStencilBits = 0;
731 glDesc.fFormat = desc.fFormat;
732 glDesc.fOwnsID = true;
733
734 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
735 if (!canBeTexture(desc.fFormat,
736 &internalFormat,
737 &glDesc.fUploadFormat,
738 &glDesc.fUploadType)) {
739 return return_null_texture();
740 }
741
742 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
743 GrGLint samples = fAASamples[desc.fAALevel];
744 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
745 GrPrintf("AA RT requested but not supported on this platform.");
746 }
747
748 GR_GL(GenTextures(1, &glDesc.fTextureID));
749 if (!glDesc.fTextureID) {
750 return return_null_texture();
751 }
752
753 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
754
755 // in case we need a temporary, trimmed copy of the src pixels
756 GrAutoSMalloc<128 * 128> trimStorage;
757
758 /*
759 * check if our srcData has extra bytes past each row. If so, we need
760 * to trim those off here, since GL doesn't let us pass the rowBytes as
761 * a parameter to glTexImage2D
762 */
763 if (GR_GL_SUPPORT_DESKTOP) {
764 if (srcData) {
765 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
766 rowBytes / glDesc.fUploadByteCount));
767 }
768 } else {
769 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
770 if (srcData && (trimRowBytes < rowBytes)) {
771 // copy the data into our new storage, skipping the trailing bytes
772 size_t trimSize = desc.fHeight * trimRowBytes;
773 const char* src = (const char*)srcData;
774 char* dst = (char*)trimStorage.realloc(trimSize);
775 for (uint32_t y = 0; y < desc.fHeight; y++) {
776 memcpy(dst, src, trimRowBytes);
777 src += rowBytes;
778 dst += trimRowBytes;
779 }
780 // now point srcData to our trimmed version
781 srcData = trimStorage.get();
782 }
783 }
784
785 if (renderTarget) {
786 if (!this->npotRenderTargetSupport()) {
787 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
788 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
789 }
790
791 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
792 glDesc.fAllocWidth);
793 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
794 glDesc.fAllocHeight);
795 } else if (!this->npotTextureSupport()) {
796 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
797 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
798 }
799
800 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
801 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
802 GR_GL_TEXTURE_MAG_FILTER,
803 DEFAULT_PARAMS.fFilter));
804 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
805 GR_GL_TEXTURE_MIN_FILTER,
806 DEFAULT_PARAMS.fFilter));
807 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
808 GR_GL_TEXTURE_WRAP_S,
809 DEFAULT_PARAMS.fWrapS));
810 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
811 GR_GL_TEXTURE_WRAP_T,
812 DEFAULT_PARAMS.fWrapT));
813
814 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
815 if (kIndex_8_GrPixelConfig == desc.fFormat &&
816 supports8BitPalette()) {
817 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
818 GrAssert(desc.fWidth == glDesc.fAllocWidth);
819 GrAssert(desc.fHeight == glDesc.fAllocHeight);
820 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
821 kGrColorTableSize;
822 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
823 glDesc.fAllocWidth, glDesc.fAllocHeight,
824 0, imageSize, srcData));
825 GrGLRestoreResetRowLength();
826 } else {
827 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
828 glDesc.fAllocHeight != desc.fHeight)) {
829 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
830 glDesc.fAllocWidth, glDesc.fAllocHeight,
831 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
832 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
833 desc.fHeight, glDesc.fUploadFormat,
834 glDesc.fUploadType, srcData));
835 GrGLRestoreResetRowLength();
836
837 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
838 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
839 uint32_t maxTexels = extraW * extraH;
840 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
841 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
842
843 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
844
845 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
846 if (extraH) {
847 uint8_t* lastRowStart = (uint8_t*) srcData +
848 (desc.fHeight - 1) * rowSize;
849 uint8_t* extraRowStart = (uint8_t*)texels.get();
850
851 for (uint32_t i = 0; i < extraH; ++i) {
852 memcpy(extraRowStart, lastRowStart, rowSize);
853 extraRowStart += rowSize;
854 }
855 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
856 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
857 texels.get()));
858 }
859 if (extraW) {
860 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
861 uint8_t* extraTexel = (uint8_t*)texels.get();
862 for (uint32_t j = 0; j < desc.fHeight; ++j) {
863 for (uint32_t i = 0; i < extraW; ++i) {
864 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
865 extraTexel += glDesc.fUploadByteCount;
866 }
867 edgeTexel += rowSize;
868 }
869 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
870 desc.fHeight, glDesc.fUploadFormat,
871 glDesc.fUploadType, texels.get()));
872 }
873 if (extraW && extraH) {
874 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
875 - glDesc.fUploadByteCount;
876 uint8_t* extraTexel = (uint8_t*)texels.get();
877 for (uint32_t i = 0; i < extraW*extraH; ++i) {
878 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
879 extraTexel += glDesc.fUploadByteCount;
880 }
881 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
882 extraW, extraH, glDesc.fUploadFormat,
883 glDesc.fUploadType, texels.get()));
884 }
885
886 } else {
887 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
888 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
889 glDesc.fUploadType, srcData));
890 GrGLRestoreResetRowLength();
891 }
892 }
893
894 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
895
896 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
897 rtIDs.fStencilRenderbufferID = 0;
898 rtIDs.fMSColorRenderbufferID = 0;
899 rtIDs.fRTFBOID = 0;
900 rtIDs.fTexFBOID = 0;
901 rtIDs.fOwnIDs = true;
902 GrGLenum msColorRenderbufferFormat = -1;
903
904 if (renderTarget) {
905 #if GR_COLLECT_STATS
906 ++fStats.fRenderTargetCreateCnt;
907 #endif
908 bool failed = true;
909 GrGLenum status;
910 GrGLint err;
911
912 // If need have both RT flag and srcData we have
913 // to invert the data before uploading because FBO
914 // will be rendered bottom up
915 GrAssert(NULL == srcData);
916 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
917
918 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
919 GrAssert(rtIDs.fTexFBOID);
920
921 // If we are using multisampling and we will create two FBOS We render
922 // to one and then resolve to the texture bound to the other.
923 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
924 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
925 GrAssert(0 != rtIDs.fRTFBOID);
926 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
927 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
928 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
929 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
930 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
931 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
932 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
933 return return_null_texture();
934 }
935 } else {
936 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
937 }
938 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
939 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
940 GrAssert(0 != rtIDs.fStencilRenderbufferID);
941 }
942
943 // someone suggested that some systems might require
944 // unbinding the texture before we call FramebufferTexture2D
945 // (seems unlikely)
946 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
947
948 err = ~GR_GL_NO_ERROR;
949
950 const StencilFormat* stencilFormats = GrGLStencilFormats();
951 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
952 if (rtIDs.fStencilRenderbufferID) {
953 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
954 rtIDs.fStencilRenderbufferID));
955 if (samples > 1) {
956 GR_GL_NO_ERR(RenderbufferStorageMultisample(
957 GR_GL_RENDERBUFFER,
958 samples,
959 stencilFormats[i].fEnum,
960 glDesc.fAllocWidth,
961 glDesc.fAllocHeight));
962 } else {
963 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
964 stencilFormats[i].fEnum,
965 glDesc.fAllocWidth,
966 glDesc.fAllocHeight));
967 }
968 err = GrGLGetGLInterface()->fGetError();
969 if (err != GR_GL_NO_ERROR) {
970 continue;
971 }
972 }
973 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
974 GrAssert(samples > 1);
975 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
976 rtIDs.fMSColorRenderbufferID));
977 GR_GL_NO_ERR(RenderbufferStorageMultisample(
978 GR_GL_RENDERBUFFER,
979 samples,
980 msColorRenderbufferFormat,
981 glDesc.fAllocWidth,
982 glDesc.fAllocHeight));
983 err = GrGLGetGLInterface()->fGetError();
984 if (err != GR_GL_NO_ERROR) {
985 continue;
986 }
987 }
988 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
989
990 #if GR_COLLECT_STATS
991 ++fStats.fRenderTargetChngCnt;
992 #endif
993 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
994 GR_GL_COLOR_ATTACHMENT0,
995 GR_GL_TEXTURE_2D,
996 glDesc.fTextureID, 0));
997 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
998 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
999 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1000 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1001 status, desc.fWidth, desc.fHeight);
1002 continue;
1003 }
1004 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
1005 #if GR_COLLECT_STATS
1006 ++fStats.fRenderTargetChngCnt;
1007 #endif
1008 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1009 GR_GL_COLOR_ATTACHMENT0,
1010 GR_GL_RENDERBUFFER,
1011 rtIDs.fMSColorRenderbufferID));
1012
1013 }
1014 if (rtIDs.fStencilRenderbufferID) {
1015 // bind the stencil to rt fbo if present, othewise the tex fbo
1016 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1017 GR_GL_STENCIL_ATTACHMENT,
1018 GR_GL_RENDERBUFFER,
1019 rtIDs.fStencilRenderbufferID));
1020 // if it is a packed format bind to depth also, otherwise
1021 // we may get an unsupported fbo completeness result
1022 if (stencilFormats[i].fPacked) {
1023 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1024 GR_GL_DEPTH_ATTACHMENT,
1025 GR_GL_RENDERBUFFER,
1026 rtIDs.fStencilRenderbufferID));
1027 }
1028 }
1029 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1030
1031 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1032 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1033 status, desc.fWidth, desc.fHeight);
1034 // undo the depth bind
1035 if (rtIDs.fStencilRenderbufferID &&
1036 stencilFormats[i].fPacked) {
1037 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1038 GR_GL_DEPTH_ATTACHMENT,
1039 GR_GL_RENDERBUFFER,
1040 0));
1041 }
1042 continue;
1043 }
1044 // we're successful!
1045 failed = false;
1046 if (rtIDs.fStencilRenderbufferID) {
1047 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
1048 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
1049 } else {
1050 glDesc.fStencilBits = stencilFormats[i].fBits;
1051 }
1052 }
1053 break;
1054 }
1055 if (failed) {
1056 if (rtIDs.fStencilRenderbufferID) {
1057 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
1058 }
1059 if (rtIDs.fMSColorRenderbufferID) {
1060 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
1061 }
1062 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
1063 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
1064 }
1065 if (rtIDs.fTexFBOID) {
1066 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
1067 }
1068 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1069 return return_null_texture();
1070 }
1071 }
1072 #ifdef TRACE_TEXTURE_CREATION
1073 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1074 tex->fTextureID, width, height, tex->fUploadByteCount);
1075 #endif
1076 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
1077
1078 if (0 != rtIDs.fTexFBOID) {
1079 GrRenderTarget* rt = tex->asRenderTarget();
1080 // We've messed with FBO state but may not have set the correct viewport
1081 // so just dirty the rendertarget state to force a resend.
1082 fHWDrawState.fRenderTarget = NULL;
1083
1084 // clear the new stencil buffer if we have one
1085 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
1086 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1087 fCurrDrawState.fRenderTarget = rt;
1088 this->clearStencil(0, ~0);
1089 fCurrDrawState.fRenderTarget = rtSave;
1090 }
1091 }
1092 return tex;
1093 }
1094
onCreateVertexBuffer(uint32_t size,bool dynamic)1095 GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
1096 GrGLuint id;
1097 GR_GL(GenBuffers(1, &id));
1098 if (id) {
1099 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
1100 fHWGeometryState.fArrayPtrsDirty = true;
1101 GrGLClearErr();
1102 // make sure driver can allocate memory for this buffer
1103 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1104 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1105 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
1106 GR_GL(DeleteBuffers(1, &id));
1107 // deleting bound buffer does implicit bind to 0
1108 fHWGeometryState.fVertexBuffer = NULL;
1109 return NULL;
1110 }
1111 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
1112 size, dynamic);
1113 fHWGeometryState.fVertexBuffer = vertexBuffer;
1114 return vertexBuffer;
1115 }
1116 return NULL;
1117 }
1118
onCreateIndexBuffer(uint32_t size,bool dynamic)1119 GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
1120 GrGLuint id;
1121 GR_GL(GenBuffers(1, &id));
1122 if (id) {
1123 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
1124 GrGLClearErr();
1125 // make sure driver can allocate memory for this buffer
1126 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1127 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1128 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
1129 GR_GL(DeleteBuffers(1, &id));
1130 // deleting bound buffer does implicit bind to 0
1131 fHWGeometryState.fIndexBuffer = NULL;
1132 return NULL;
1133 }
1134 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
1135 size, dynamic);
1136 fHWGeometryState.fIndexBuffer = indexBuffer;
1137 return indexBuffer;
1138 }
1139 return NULL;
1140 }
1141
flushScissor(const GrIRect * rect)1142 void GrGpuGL::flushScissor(const GrIRect* rect) {
1143 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1144 const GrGLIRect& vp =
1145 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
1146
1147 GrGLIRect scissor;
1148 if (NULL != rect) {
1149 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
1150 rect->width(), rect->height());
1151 if (scissor.contains(vp)) {
1152 rect = NULL;
1153 }
1154 }
1155
1156 if (NULL != rect) {
1157 if (fHWBounds.fScissorRect != scissor) {
1158 scissor.pushToGLScissor();
1159 fHWBounds.fScissorRect = scissor;
1160 }
1161 if (!fHWBounds.fScissorEnabled) {
1162 GR_GL(Enable(GR_GL_SCISSOR_TEST));
1163 fHWBounds.fScissorEnabled = true;
1164 }
1165 } else {
1166 if (fHWBounds.fScissorEnabled) {
1167 GR_GL(Disable(GR_GL_SCISSOR_TEST));
1168 fHWBounds.fScissorEnabled = false;
1169 }
1170 }
1171 }
1172
onClear(const GrIRect * rect,GrColor color)1173 void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
1174 if (NULL == fCurrDrawState.fRenderTarget) {
1175 return;
1176 }
1177 GrIRect r;
1178 if (NULL != rect) {
1179 // flushScissor expects rect to be clipped to the target.
1180 r = *rect;
1181 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1182 fCurrDrawState.fRenderTarget->height());
1183 if (r.intersect(rtRect)) {
1184 rect = &r;
1185 } else {
1186 return;
1187 }
1188 }
1189 this->flushRenderTarget(rect);
1190 this->flushScissor(rect);
1191 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
1192 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
1193 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1194 GrColorUnpackG(color)/255.f,
1195 GrColorUnpackB(color)/255.f,
1196 GrColorUnpackA(color)/255.f));
1197 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
1198 }
1199
clearStencil(uint32_t value,uint32_t mask)1200 void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
1201 if (NULL == fCurrDrawState.fRenderTarget) {
1202 return;
1203 }
1204
1205 this->flushRenderTarget(&GrIRect::EmptyIRect());
1206
1207 if (fHWBounds.fScissorEnabled) {
1208 GR_GL(Disable(GR_GL_SCISSOR_TEST));
1209 fHWBounds.fScissorEnabled = false;
1210 }
1211 GR_GL(StencilMask(mask));
1212 GR_GL(ClearStencil(value));
1213 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
1214 fHWDrawState.fStencilSettings.invalidate();
1215 }
1216
clearStencilClip(const GrIRect & rect)1217 void GrGpuGL::clearStencilClip(const GrIRect& rect) {
1218 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1219 #if 0
1220 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
1221 GrAssert(stencilBitCount > 0);
1222 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
1223 #else
1224 // we could just clear the clip bit but when we go through
1225 // angle a partial stencil mask will cause clears to be
1226 // turned into draws. Our contract on GrDrawTarget says that
1227 // changing the clip between stencil passes may or may not
1228 // zero the client's clip bits. So we just clear the whole thing.
1229 static const GrGLint clipStencilMask = ~0;
1230 #endif
1231 this->flushRenderTarget(&GrIRect::EmptyIRect());
1232 flushScissor(&rect);
1233 GR_GL(StencilMask(clipStencilMask));
1234 GR_GL(ClearStencil(0));
1235 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
1236 fHWDrawState.fStencilSettings.invalidate();
1237 }
1238
onForceRenderTargetFlush()1239 void GrGpuGL::onForceRenderTargetFlush() {
1240 this->flushRenderTarget(&GrIRect::EmptyIRect());
1241 }
1242
onReadPixels(GrRenderTarget * target,int left,int top,int width,int height,GrPixelConfig config,void * buffer)1243 bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1244 int left, int top, int width, int height,
1245 GrPixelConfig config, void* buffer) {
1246 GrGLenum internalFormat; // we don't use this for glReadPixels
1247 GrGLenum format;
1248 GrGLenum type;
1249 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1250 return false;
1251 }
1252 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1253 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1254 switch (tgt->getResolveType()) {
1255 case GrGLRenderTarget::kCantResolve_ResolveType:
1256 return false;
1257 case GrGLRenderTarget::kAutoResolves_ResolveType:
1258 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1259 fCurrDrawState.fRenderTarget = target;
1260 this->flushRenderTarget(&GrIRect::EmptyIRect());
1261 break;
1262 case GrGLRenderTarget::kCanResolve_ResolveType:
1263 this->resolveRenderTarget(tgt);
1264 // we don't track the state of the READ FBO ID.
1265 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1266 break;
1267 default:
1268 GrCrash("Unknown resolve type");
1269 }
1270
1271 const GrGLIRect& glvp = tgt->getViewport();
1272
1273 // the read rect is viewport-relative
1274 GrGLIRect readRect;
1275 readRect.setRelativeTo(glvp, left, top, width, height);
1276 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
1277 readRect.fWidth, readRect.fHeight,
1278 format, type, buffer));
1279
1280 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1281 // API presents top-to-bottom
1282 {
1283 size_t stride = width * GrBytesPerPixel(config);
1284 GrAutoMalloc rowStorage(stride);
1285 void* tmp = rowStorage.get();
1286
1287 const int halfY = height >> 1;
1288 char* top = reinterpret_cast<char*>(buffer);
1289 char* bottom = top + (height - 1) * stride;
1290 for (int y = 0; y < halfY; y++) {
1291 memcpy(tmp, top, stride);
1292 memcpy(top, bottom, stride);
1293 memcpy(bottom, tmp, stride);
1294 top += stride;
1295 bottom -= stride;
1296 }
1297 }
1298 return true;
1299 }
1300
flushRenderTarget(const GrIRect * bound)1301 void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
1302
1303 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1304
1305 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
1306 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1307 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
1308 #if GR_COLLECT_STATS
1309 ++fStats.fRenderTargetChngCnt;
1310 #endif
1311 #if GR_DEBUG
1312 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1313 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
1314 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1315 }
1316 #endif
1317 fDirtyFlags.fRenderTargetChanged = true;
1318 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
1319 const GrGLIRect& vp = rt->getViewport();
1320 if (fHWBounds.fViewportRect != vp) {
1321 vp.pushToGLViewport();
1322 fHWBounds.fViewportRect = vp;
1323 }
1324 }
1325 if (NULL == bound || !bound->isEmpty()) {
1326 rt->flagAsNeedingResolve(bound);
1327 }
1328 }
1329
1330 GrGLenum gPrimitiveType2GLMode[] = {
1331 GR_GL_TRIANGLES,
1332 GR_GL_TRIANGLE_STRIP,
1333 GR_GL_TRIANGLE_FAN,
1334 GR_GL_POINTS,
1335 GR_GL_LINES,
1336 GR_GL_LINE_STRIP
1337 };
1338
1339 #define SWAP_PER_DRAW 0
1340
1341 #if SWAP_PER_DRAW
1342 #if GR_MAC_BUILD
1343 #include <AGL/agl.h>
1344 #elif GR_WIN32_BUILD
SwapBuf()1345 void SwapBuf() {
1346 DWORD procID = GetCurrentProcessId();
1347 HWND hwnd = GetTopWindow(GetDesktopWindow());
1348 while(hwnd) {
1349 DWORD wndProcID = 0;
1350 GetWindowThreadProcessId(hwnd, &wndProcID);
1351 if(wndProcID == procID) {
1352 SwapBuffers(GetDC(hwnd));
1353 }
1354 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1355 }
1356 }
1357 #endif
1358 #endif
1359
onDrawIndexed(GrPrimitiveType type,uint32_t startVertex,uint32_t startIndex,uint32_t vertexCount,uint32_t indexCount)1360 void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1361 uint32_t startVertex,
1362 uint32_t startIndex,
1363 uint32_t vertexCount,
1364 uint32_t indexCount) {
1365 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1366
1367 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
1368
1369 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1370 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1371
1372 // our setupGeometry better have adjusted this to zero since
1373 // DrawElements always draws from the begining of the arrays for idx 0.
1374 GrAssert(0 == startVertex);
1375
1376 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
1377 GR_GL_UNSIGNED_SHORT, indices));
1378 #if SWAP_PER_DRAW
1379 glFlush();
1380 #if GR_MAC_BUILD
1381 aglSwapBuffers(aglGetCurrentContext());
1382 int set_a_break_pt_here = 9;
1383 aglSwapBuffers(aglGetCurrentContext());
1384 #elif GR_WIN32_BUILD
1385 SwapBuf();
1386 int set_a_break_pt_here = 9;
1387 SwapBuf();
1388 #endif
1389 #endif
1390 }
1391
onDrawNonIndexed(GrPrimitiveType type,uint32_t startVertex,uint32_t vertexCount)1392 void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1393 uint32_t startVertex,
1394 uint32_t vertexCount) {
1395 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1396
1397 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1398
1399 // our setupGeometry better have adjusted this to zero.
1400 // DrawElements doesn't take an offset so we always adjus the startVertex.
1401 GrAssert(0 == startVertex);
1402
1403 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1404 // account for startVertex in the DrawElements case. So we always
1405 // rely on setupGeometry to have accounted for startVertex.
1406 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
1407 #if SWAP_PER_DRAW
1408 glFlush();
1409 #if GR_MAC_BUILD
1410 aglSwapBuffers(aglGetCurrentContext());
1411 int set_a_break_pt_here = 9;
1412 aglSwapBuffers(aglGetCurrentContext());
1413 #elif GR_WIN32_BUILD
1414 SwapBuf();
1415 int set_a_break_pt_here = 9;
1416 SwapBuf();
1417 #endif
1418 #endif
1419 }
1420
resolveRenderTarget(GrGLRenderTarget * rt)1421 void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
1422
1423 if (rt->needsResolve()) {
1424 GrAssert(kNone_MSFBO != fMSFBOType);
1425 GrAssert(rt->textureFBOID() != rt->renderFBOID());
1426 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
1427 rt->renderFBOID()));
1428 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
1429 rt->textureFBOID()));
1430 #if GR_COLLECT_STATS
1431 ++fStats.fRenderTargetChngCnt;
1432 #endif
1433 // make sure we go through flushRenderTarget() since we've modified
1434 // the bound DRAW FBO ID.
1435 fHWDrawState.fRenderTarget = NULL;
1436 const GrGLIRect& vp = rt->getViewport();
1437 const GrIRect dirtyRect = rt->getResolveRect();
1438 GrGLIRect r;
1439 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1440 dirtyRect.width(), dirtyRect.height());
1441
1442 if (kAppleES_MSFBO == fMSFBOType) {
1443 // Apple's extension uses the scissor as the blit bounds.
1444 GR_GL(Enable(GR_GL_SCISSOR_TEST));
1445 GR_GL(Scissor(r.fLeft, r.fBottom,
1446 r.fWidth, r.fHeight));
1447 GR_GL(ResolveMultisampleFramebuffer());
1448 fHWBounds.fScissorRect.invalidate();
1449 fHWBounds.fScissorEnabled = true;
1450 } else {
1451 if (kDesktopARB_MSFBO != fMSFBOType) {
1452 // this respects the scissor during the blit, so disable it.
1453 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1454 flushScissor(NULL);
1455 }
1456 int right = r.fLeft + r.fWidth;
1457 int top = r.fBottom + r.fHeight;
1458 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1459 r.fLeft, r.fBottom, right, top,
1460 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
1461 }
1462 rt->flagAsResolved();
1463 }
1464 }
1465
1466 static const GrGLenum grToGLStencilFunc[] = {
1467 GR_GL_ALWAYS, // kAlways_StencilFunc
1468 GR_GL_NEVER, // kNever_StencilFunc
1469 GR_GL_GREATER, // kGreater_StencilFunc
1470 GR_GL_GEQUAL, // kGEqual_StencilFunc
1471 GR_GL_LESS, // kLess_StencilFunc
1472 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1473 GR_GL_EQUAL, // kEqual_StencilFunc,
1474 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
1475 };
1476 GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1477 GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1478 GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1479 GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1480 GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1481 GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1482 GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1483 GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1484 GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1485
1486 static const GrGLenum grToGLStencilOp[] = {
1487 GR_GL_KEEP, // kKeep_StencilOp
1488 GR_GL_REPLACE, // kReplace_StencilOp
1489 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1490 GR_GL_INCR, // kIncClamp_StencilOp
1491 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1492 GR_GL_DECR, // kDecClamp_StencilOp
1493 GR_GL_ZERO, // kZero_StencilOp
1494 GR_GL_INVERT, // kInvert_StencilOp
1495 };
1496 GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1497 GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1498 GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1499 GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1500 GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1501 GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1502 GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1503 GR_STATIC_ASSERT(6 == kZero_StencilOp);
1504 GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1505
flushStencil()1506 void GrGpuGL::flushStencil() {
1507 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
1508
1509 // use stencil for clipping if clipping is enabled and the clip
1510 // has been written into the stencil.
1511 bool stencilClip = fClipState.fClipInStencil &&
1512 (kClip_StateBit & fCurrDrawState.fFlagBits);
1513 bool stencilChange = fHWStencilClip != stencilClip ||
1514 fHWDrawState.fStencilSettings != *settings ||
1515 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1516 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
1517
1518 if (stencilChange) {
1519
1520 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1521 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
1522
1523 if (settings->isDisabled()) {
1524 if (stencilClip) {
1525 settings = &gClipStencilSettings;
1526 }
1527 }
1528
1529 if (settings->isDisabled()) {
1530 GR_GL(Disable(GR_GL_STENCIL_TEST));
1531 } else {
1532 GR_GL(Enable(GR_GL_STENCIL_TEST));
1533 #if GR_DEBUG
1534 if (!fStencilWrapOpsSupport) {
1535 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1536 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1537 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1538 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1539 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1540 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1541 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1542 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1543 }
1544 #endif
1545 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1546 GrAssert(stencilBits ||
1547 (GrStencilSettings::gDisabled ==
1548 fCurrDrawState.fStencilSettings));
1549 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1550 GrGLuint userStencilMask = clipStencilMask - 1;
1551
1552 unsigned int frontRef = settings->fFrontFuncRef;
1553 unsigned int frontMask = settings->fFrontFuncMask;
1554 unsigned int frontWriteMask = settings->fFrontWriteMask;
1555 GrGLenum frontFunc;
1556
1557 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1558
1559 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1560 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1561 } else {
1562 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1563
1564 ConvertStencilFuncAndMask(settings->fFrontFunc,
1565 stencilClip,
1566 clipStencilMask,
1567 userStencilMask,
1568 &frontRef,
1569 &frontMask);
1570 frontWriteMask &= userStencilMask;
1571 }
1572 GrAssert(settings->fFrontFailOp >= 0 &&
1573 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
1574 GrAssert(settings->fFrontPassOp >= 0 &&
1575 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
1576 GrAssert(settings->fBackFailOp >= 0 &&
1577 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
1578 GrAssert(settings->fBackPassOp >= 0 &&
1579 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
1580 if (fTwoSidedStencilSupport) {
1581 GrGLenum backFunc;
1582
1583 unsigned int backRef = settings->fBackFuncRef;
1584 unsigned int backMask = settings->fBackFuncMask;
1585 unsigned int backWriteMask = settings->fBackWriteMask;
1586
1587
1588 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1589 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1590 backFunc = grToGLStencilFunc[settings->fBackFunc];
1591 } else {
1592 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1593 ConvertStencilFuncAndMask(settings->fBackFunc,
1594 stencilClip,
1595 clipStencilMask,
1596 userStencilMask,
1597 &backRef,
1598 &backMask);
1599 backWriteMask &= userStencilMask;
1600 }
1601
1602 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1603 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1604 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1605 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1606 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
1607 grToGLStencilOp[settings->fFrontPassOp],
1608 grToGLStencilOp[settings->fFrontPassOp]));
1609
1610 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
1611 grToGLStencilOp[settings->fBackPassOp],
1612 grToGLStencilOp[settings->fBackPassOp]));
1613 } else {
1614 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1615 GR_GL(StencilMask(frontWriteMask));
1616 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1617 grToGLStencilOp[settings->fFrontPassOp],
1618 grToGLStencilOp[settings->fFrontPassOp]));
1619 }
1620 }
1621 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
1622 fHWStencilClip = stencilClip;
1623 }
1624 }
1625
useSmoothLines()1626 bool GrGpuGL::useSmoothLines() {
1627 // there is a conflict between using smooth lines and our use of
1628 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1629 // but not in a premul-alpha way. So we only use them when our alpha
1630 // is 0xff.
1631
1632 // TODO: write a smarter line frag shader.
1633
1634 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1635 canDisableBlend();
1636 }
1637
flushAAState(GrPrimitiveType type)1638 void GrGpuGL::flushAAState(GrPrimitiveType type) {
1639 if (GR_GL_SUPPORT_DESKTOP) {
1640 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1641 // smooth lines.
1642
1643 // we prefer smooth lines over multisampled lines
1644 // msaa should be disabled if drawing smooth lines.
1645 if (GrIsPrimTypeLines(type)) {
1646 bool smooth = useSmoothLines();
1647 if (!fHWAAState.fSmoothLineEnabled && smooth) {
1648 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1649 fHWAAState.fSmoothLineEnabled = true;
1650 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
1651 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1652 fHWAAState.fSmoothLineEnabled = false;
1653 }
1654 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1655 fHWAAState.fMSAAEnabled) {
1656 GR_GL(Disable(GR_GL_MULTISAMPLE));
1657 fHWAAState.fMSAAEnabled = false;
1658 }
1659 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1660 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1661 fHWAAState.fMSAAEnabled) {
1662 if (fHWAAState.fMSAAEnabled) {
1663 GR_GL(Disable(GR_GL_MULTISAMPLE));
1664 fHWAAState.fMSAAEnabled = false;
1665 } else {
1666 GR_GL(Enable(GR_GL_MULTISAMPLE));
1667 fHWAAState.fMSAAEnabled = true;
1668 }
1669 }
1670 }
1671 }
1672
flushBlend(GrPrimitiveType type,GrBlendCoeff srcCoeff,GrBlendCoeff dstCoeff)1673 void GrGpuGL::flushBlend(GrPrimitiveType type,
1674 GrBlendCoeff srcCoeff,
1675 GrBlendCoeff dstCoeff) {
1676 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1677 if (fHWBlendDisabled) {
1678 GR_GL(Enable(GR_GL_BLEND));
1679 fHWBlendDisabled = false;
1680 }
1681 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1682 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1683 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1684 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1685 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1686 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1687 }
1688 } else {
1689 bool blendOff = canDisableBlend();
1690 if (fHWBlendDisabled != blendOff) {
1691 if (blendOff) {
1692 GR_GL(Disable(GR_GL_BLEND));
1693 } else {
1694 GR_GL(Enable(GR_GL_BLEND));
1695 }
1696 fHWBlendDisabled = blendOff;
1697 }
1698 if (!blendOff) {
1699 if (fHWDrawState.fSrcBlend != srcCoeff ||
1700 fHWDrawState.fDstBlend != dstCoeff) {
1701 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1702 gXfermodeCoeff2Blend[dstCoeff]));
1703 fHWDrawState.fSrcBlend = srcCoeff;
1704 fHWDrawState.fDstBlend = dstCoeff;
1705 }
1706 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1707 BlendCoeffReferencesConstant(dstCoeff)) &&
1708 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1709
1710 float c[] = {
1711 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1712 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1713 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1714 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1715 };
1716 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1717 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1718 }
1719 }
1720 }
1721 }
1722
flushGLStateCommon(GrPrimitiveType type)1723 bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
1724
1725 // GrGpu::setupClipAndFlushState should have already checked this
1726 // and bailed if not true.
1727 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1728
1729 for (int s = 0; s < kNumStages; ++s) {
1730 // bind texture and set sampler state
1731 if (this->isStageEnabled(s)) {
1732 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
1733
1734 // true for now, but maybe not with GrEffect.
1735 GrAssert(NULL != nextTexture);
1736 // if we created a rt/tex and rendered to it without using a
1737 // texture and now we're texuring from the rt it will still be
1738 // the last bound texture, but it needs resolving. So keep this
1739 // out of the "last != next" check.
1740 GrGLRenderTarget* texRT =
1741 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1742 if (NULL != texRT) {
1743 resolveRenderTarget(texRT);
1744 }
1745
1746 if (fHWDrawState.fTextures[s] != nextTexture) {
1747 setTextureUnit(s);
1748 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1749 #if GR_COLLECT_STATS
1750 ++fStats.fTextureChngCnt;
1751 #endif
1752 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1753 fHWDrawState.fTextures[s] = nextTexture;
1754 }
1755
1756 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1757 const GrGLTexture::TexParams& oldTexParams =
1758 nextTexture->getTexParams();
1759 GrGLTexture::TexParams newTexParams;
1760
1761 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1762 newTexParams.fFilter = GR_GL_NEAREST;
1763 } else {
1764 newTexParams.fFilter = GR_GL_LINEAR;
1765 }
1766
1767 newTexParams.fWrapS =
1768 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1769 newTexParams.fWrapT =
1770 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1771
1772 if (newTexParams.fFilter != oldTexParams.fFilter) {
1773 setTextureUnit(s);
1774 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1775 GR_GL_TEXTURE_MAG_FILTER,
1776 newTexParams.fFilter));
1777 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1778 GR_GL_TEXTURE_MIN_FILTER,
1779 newTexParams.fFilter));
1780 }
1781 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1782 setTextureUnit(s);
1783 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1784 GR_GL_TEXTURE_WRAP_S,
1785 newTexParams.fWrapS));
1786 }
1787 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1788 setTextureUnit(s);
1789 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1790 GR_GL_TEXTURE_WRAP_T,
1791 newTexParams.fWrapT));
1792 }
1793 nextTexture->setTexParams(newTexParams);
1794
1795 // The texture matrix has to compensate for texture width/height
1796 // and NPOT-embedded-in-POT
1797 fDirtyFlags.fTextureChangedMask |= (1 << s);
1798 }
1799 }
1800
1801 GrIRect* rect = NULL;
1802 GrIRect clipBounds;
1803 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1804 fClip.hasConservativeBounds()) {
1805 fClip.getConservativeBounds().roundOut(&clipBounds);
1806 rect = &clipBounds;
1807 }
1808 this->flushRenderTarget(rect);
1809 this->flushAAState(type);
1810
1811 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1812 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1813 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
1814 GR_GL(Enable(GR_GL_DITHER));
1815 } else {
1816 GR_GL(Disable(GR_GL_DITHER));
1817 }
1818 }
1819
1820 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1821 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
1822 GrGLenum mask;
1823 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
1824 mask = GR_GL_FALSE;
1825 } else {
1826 mask = GR_GL_TRUE;
1827 }
1828 GR_GL(ColorMask(mask, mask, mask, mask));
1829 }
1830
1831 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1832 switch (fCurrDrawState.fDrawFace) {
1833 case kCCW_DrawFace:
1834 GR_GL(Enable(GR_GL_CULL_FACE));
1835 GR_GL(CullFace(GR_GL_BACK));
1836 break;
1837 case kCW_DrawFace:
1838 GR_GL(Enable(GR_GL_CULL_FACE));
1839 GR_GL(CullFace(GR_GL_FRONT));
1840 break;
1841 case kBoth_DrawFace:
1842 GR_GL(Disable(GR_GL_CULL_FACE));
1843 break;
1844 default:
1845 GrCrash("Unknown draw face.");
1846 }
1847 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1848 }
1849
1850 #if GR_DEBUG
1851 // check for circular rendering
1852 for (int s = 0; s < kNumStages; ++s) {
1853 GrAssert(!this->isStageEnabled(s) ||
1854 NULL == fCurrDrawState.fRenderTarget ||
1855 NULL == fCurrDrawState.fTextures[s] ||
1856 fCurrDrawState.fTextures[s]->asRenderTarget() !=
1857 fCurrDrawState.fRenderTarget);
1858 }
1859 #endif
1860
1861 flushStencil();
1862
1863 // flushStencil may look at the private state bits, so keep it before this.
1864 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
1865 return true;
1866 }
1867
notifyVertexBufferBind(const GrGLVertexBuffer * buffer)1868 void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
1869 if (fHWGeometryState.fVertexBuffer != buffer) {
1870 fHWGeometryState.fArrayPtrsDirty = true;
1871 fHWGeometryState.fVertexBuffer = buffer;
1872 }
1873 }
1874
notifyVertexBufferDelete(const GrGLVertexBuffer * buffer)1875 void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1876 if (fHWGeometryState.fVertexBuffer == buffer) {
1877 // deleting bound buffer does implied bind to 0
1878 fHWGeometryState.fVertexBuffer = NULL;
1879 fHWGeometryState.fArrayPtrsDirty = true;
1880 }
1881 }
1882
notifyIndexBufferBind(const GrGLIndexBuffer * buffer)1883 void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1884 fGeometrySrc.fIndexBuffer = buffer;
1885 }
1886
notifyIndexBufferDelete(const GrGLIndexBuffer * buffer)1887 void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1888 if (fHWGeometryState.fIndexBuffer == buffer) {
1889 // deleting bound buffer does implied bind to 0
1890 fHWGeometryState.fIndexBuffer = NULL;
1891 }
1892 }
1893
notifyRenderTargetDelete(GrRenderTarget * renderTarget)1894 void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1895 GrAssert(NULL != renderTarget);
1896 if (fCurrDrawState.fRenderTarget == renderTarget) {
1897 fCurrDrawState.fRenderTarget = NULL;
1898 }
1899 if (fHWDrawState.fRenderTarget == renderTarget) {
1900 fHWDrawState.fRenderTarget = NULL;
1901 }
1902 }
1903
notifyTextureDelete(GrGLTexture * texture)1904 void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
1905 for (int s = 0; s < kNumStages; ++s) {
1906 if (fCurrDrawState.fTextures[s] == texture) {
1907 fCurrDrawState.fTextures[s] = NULL;
1908 }
1909 if (fHWDrawState.fTextures[s] == texture) {
1910 // deleting bound texture does implied bind to 0
1911 fHWDrawState.fTextures[s] = NULL;
1912 }
1913 }
1914 }
1915
canBeTexture(GrPixelConfig config,GrGLenum * internalFormat,GrGLenum * format,GrGLenum * type)1916 bool GrGpuGL::canBeTexture(GrPixelConfig config,
1917 GrGLenum* internalFormat,
1918 GrGLenum* format,
1919 GrGLenum* type) {
1920 switch (config) {
1921 case kRGBA_8888_GrPixelConfig:
1922 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
1923 *format = GR_GL_32BPP_COLOR_FORMAT;
1924 if (GR_GL_SUPPORT_ES) {
1925 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1926 // format for a BGRA is BGRA not RGBA (as on desktop)
1927 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1928 } else {
1929 *internalFormat = GR_GL_RGBA;
1930 }
1931 *type = GR_GL_UNSIGNED_BYTE;
1932 break;
1933 case kRGB_565_GrPixelConfig:
1934 *format = GR_GL_RGB;
1935 *internalFormat = GR_GL_RGB;
1936 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
1937 break;
1938 case kRGBA_4444_GrPixelConfig:
1939 *format = GR_GL_RGBA;
1940 *internalFormat = GR_GL_RGBA;
1941 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
1942 break;
1943 case kIndex_8_GrPixelConfig:
1944 if (this->supports8BitPalette()) {
1945 *format = GR_GL_PALETTE8_RGBA8;
1946 *internalFormat = GR_GL_PALETTE8_RGBA8;
1947 *type = GR_GL_UNSIGNED_BYTE; // unused I think
1948 } else {
1949 return false;
1950 }
1951 break;
1952 case kAlpha_8_GrPixelConfig:
1953 *format = GR_GL_ALPHA;
1954 *internalFormat = GR_GL_ALPHA;
1955 *type = GR_GL_UNSIGNED_BYTE;
1956 break;
1957 default:
1958 return false;
1959 }
1960 return true;
1961 }
1962
setTextureUnit(int unit)1963 void GrGpuGL::setTextureUnit(int unit) {
1964 GrAssert(unit >= 0 && unit < kNumStages);
1965 if (fActiveTextureUnitIdx != unit) {
1966 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
1967 fActiveTextureUnitIdx = unit;
1968 }
1969 }
1970
setSpareTextureUnit()1971 void GrGpuGL::setSpareTextureUnit() {
1972 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1973 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
1974 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1975 }
1976 }
1977
1978 /* On ES the internalFormat and format must match for TexImage and we use
1979 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1980 decide the internalFormat. However, on ES internalFormat for
1981 RenderBufferStorage* has to be a specific format (not a base format like
1982 GL_RGBA).
1983 */
fboInternalFormat(GrPixelConfig config,GrGLenum * format)1984 bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
1985 switch (config) {
1986 case kRGBA_8888_GrPixelConfig:
1987 case kRGBX_8888_GrPixelConfig:
1988 if (fRGBA8Renderbuffer) {
1989 *format = GR_GL_RGBA8;
1990 return true;
1991 } else {
1992 return false;
1993 }
1994 case kRGB_565_GrPixelConfig:
1995 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1996 // with FBO extension desktop GL has
1997 // no such internal format
1998 *format = GR_GL_RGB565;
1999 return true;
2000 case kRGBA_4444_GrPixelConfig:
2001 *format = GR_GL_RGBA4;
2002 return true;
2003 default:
2004 return false;
2005 }
2006 }
2007
resetDirtyFlags()2008 void GrGpuGL::resetDirtyFlags() {
2009 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2010 }
2011
setBuffers(bool indexed,int * extraVertexOffset,int * extraIndexOffset)2012 void GrGpuGL::setBuffers(bool indexed,
2013 int* extraVertexOffset,
2014 int* extraIndexOffset) {
2015
2016 GrAssert(NULL != extraVertexOffset);
2017
2018 GrGLVertexBuffer* vbuf;
2019 switch (fGeometrySrc.fVertexSrc) {
2020 case kBuffer_GeometrySrcType:
2021 *extraVertexOffset = 0;
2022 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2023 break;
2024 case kArray_GeometrySrcType:
2025 case kReserved_GeometrySrcType:
2026 finalizeReservedVertices();
2027 *extraVertexOffset = fCurrPoolStartVertex;
2028 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2029 break;
2030 default:
2031 vbuf = NULL; // suppress warning
2032 GrCrash("Unknown geometry src type!");
2033 }
2034
2035 GrAssert(NULL != vbuf);
2036 GrAssert(!vbuf->isLocked());
2037 if (fHWGeometryState.fVertexBuffer != vbuf) {
2038 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
2039 fHWGeometryState.fArrayPtrsDirty = true;
2040 fHWGeometryState.fVertexBuffer = vbuf;
2041 }
2042
2043 if (indexed) {
2044 GrAssert(NULL != extraIndexOffset);
2045
2046 GrGLIndexBuffer* ibuf;
2047 switch (fGeometrySrc.fIndexSrc) {
2048 case kBuffer_GeometrySrcType:
2049 *extraIndexOffset = 0;
2050 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2051 break;
2052 case kArray_GeometrySrcType:
2053 case kReserved_GeometrySrcType:
2054 finalizeReservedIndices();
2055 *extraIndexOffset = fCurrPoolStartIndex;
2056 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2057 break;
2058 default:
2059 ibuf = NULL; // suppress warning
2060 GrCrash("Unknown geometry src type!");
2061 }
2062
2063 GrAssert(NULL != ibuf);
2064 GrAssert(!ibuf->isLocked());
2065 if (fHWGeometryState.fIndexBuffer != ibuf) {
2066 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
2067 fHWGeometryState.fIndexBuffer = ibuf;
2068 }
2069 }
2070 }
2071
getMaxEdges() const2072 int GrGpuGL::getMaxEdges() const {
2073 // FIXME: This is a pessimistic estimate based on how many other things
2074 // want to add uniforms. This should be centralized somewhere.
2075 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2076 }
2077