• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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