blob: 41cb32a046f071bf17baad5cafd14e4425354fed [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
bsalomon@google.com1da07462011-03-10 14:51:57 +00002 Copyright 2011 Google Inc.
reed@google.comac10a2d2010-12-22 21:39:39 +00003
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"
reed@google.comac10a2d2010-12-22 21:39:39 +000019
twiz@google.com0f31ca72011-03-18 17:38:11 +000020static const GrGLuint GR_MAX_GLUINT = ~0;
21static const GrGLint GR_INVAL_GLINT = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000022
bsalomon@google.com316f99232011-01-13 21:28:12 +000023// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000024// mucking with the state of any of the stages.
bsalomon@google.com316f99232011-01-13 21:28:12 +000025static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000026
reed@google.comac10a2d2010-12-22 21:39:39 +000027#define SKIP_CACHE_CHECK true
28
twiz@google.com0f31ca72011-03-18 17:38:11 +000029static const GrGLenum gXfermodeCoeff2Blend[] = {
30 GR_GL_ZERO,
31 GR_GL_ONE,
32 GR_GL_SRC_COLOR,
33 GR_GL_ONE_MINUS_SRC_COLOR,
34 GR_GL_DST_COLOR,
35 GR_GL_ONE_MINUS_DST_COLOR,
36 GR_GL_SRC_ALPHA,
37 GR_GL_ONE_MINUS_SRC_ALPHA,
38 GR_GL_DST_ALPHA,
39 GR_GL_ONE_MINUS_DST_ALPHA,
40 GR_GL_CONSTANT_COLOR,
41 GR_GL_ONE_MINUS_CONSTANT_COLOR,
42 GR_GL_CONSTANT_ALPHA,
43 GR_GL_ONE_MINUS_CONSTANT_ALPHA,
reed@google.comac10a2d2010-12-22 21:39:39 +000044};
45
bsalomon@google.com080773c2011-03-15 19:09:25 +000046bool GrGpuGL::BlendCoefReferencesConstant(GrBlendCoeff coeff) {
47 static const bool gCoeffReferencesBlendConst[] = {
48 false,
49 false,
50 false,
51 false,
52 false,
53 false,
54 false,
55 false,
56 false,
57 false,
58 true,
59 true,
60 true,
61 true,
62 };
63 return gCoeffReferencesBlendConst[coeff];
64 GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
65}
66
67GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
68GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
69GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
70GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
71GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
72GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
73GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
74GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
75GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
76GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
77GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
78GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
79GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
80GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
81
82GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
83
reed@google.comac10a2d2010-12-22 21:39:39 +000084///////////////////////////////////////////////////////////////////////////////
85
bsalomon@google.comd302f142011-03-03 13:54:13 +000086void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
87 GrSamplerState::SampleMode mode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000088 GrMatrix* matrix) {
89 GrAssert(NULL != texture);
90 GrAssert(NULL != matrix);
91 if (GR_Scalar1 != texture->contentScaleX() ||
92 GR_Scalar1 != texture->contentScaleY()) {
93 if (GrSamplerState::kRadial_SampleMode == mode) {
94 GrMatrix scale;
95 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
96 matrix->postConcat(scale);
97 } else if (GrSamplerState::kNormal_SampleMode == mode) {
98 GrMatrix scale;
99 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
100 matrix->postConcat(scale);
101 } else {
102 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
103 }
104 }
105 GrGLTexture::Orientation orientation = texture->orientation();
106 if (GrGLTexture::kBottomUp_Orientation == orientation) {
107 GrMatrix invY;
108 invY.setAll(GR_Scalar1, 0, 0,
109 0, -GR_Scalar1, GR_Scalar1,
110 0, 0, GrMatrix::I()[8]);
111 matrix->postConcat(invY);
112 } else {
113 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
114 }
115}
116
bsalomon@google.comd302f142011-03-03 13:54:13 +0000117bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000118 const GrSamplerState& sampler) {
119 GrAssert(NULL != texture);
120 if (!sampler.getMatrix().isIdentity()) {
121 return false;
122 }
123 if (GR_Scalar1 != texture->contentScaleX() ||
124 GR_Scalar1 != texture->contentScaleY()) {
125 return false;
126 }
127 GrGLTexture::Orientation orientation = texture->orientation();
128 if (GrGLTexture::kBottomUp_Orientation == orientation) {
129 return false;
130 } else {
131 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
132 }
133 return true;
134}
135
136///////////////////////////////////////////////////////////////////////////////
137
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000138static bool gPrintStartupSpew;
139
twiz@google.com59a190b2011-03-14 21:23:01 +0000140static bool fbo_test(int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000141
twiz@google.com0f31ca72011-03-18 17:38:11 +0000142 GrGLint savedFBO;
143 GrGLint savedTexUnit;
144 GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000145 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000146
twiz@google.com0f31ca72011-03-18 17:38:11 +0000147 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000148
twiz@google.com0f31ca72011-03-18 17:38:11 +0000149 GrGLuint testFBO;
twiz@google.com59a190b2011-03-14 21:23:01 +0000150 GR_GL(GenFramebuffers(1, &testFBO));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000151 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000152 GrGLuint testRTTex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 GR_GL(GenTextures(1, &testRTTex));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000154 GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000155 // some implementations require texture to be mip-map complete before
156 // FBO with level 0 bound as color attachment will be framebuffer complete.
twiz@google.com0f31ca72011-03-18 17:38:11 +0000157 GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
158 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
159 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
160 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000161 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000162 GR_GL_TEXTURE_2D, testRTTex, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000163 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000164 GR_GL(DeleteFramebuffers(1, &testFBO));
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000166
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000167 GR_GL(ActiveTexture(savedTexUnit));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000168 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000169
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000170 return status == GR_GL_FRAMEBUFFER_COMPLETE;
reed@google.comac10a2d2010-12-22 21:39:39 +0000171}
172
reed@google.comac10a2d2010-12-22 21:39:39 +0000173GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000174
reed@google.comeeeb5a02010-12-23 15:12:59 +0000175 if (gPrintStartupSpew) {
176 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
177 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000178 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000179 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000180 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000181 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000182 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000183 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000184 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000185 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000186 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000187
188 GrGLClearErr();
189
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000190 resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000191
twiz@google.com0f31ca72011-03-18 17:38:11 +0000192 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000193 // check FS and fixed-function texture unit limits
194 // we only use textures in the fragment stage currently.
195 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000196 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
197 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
198 GrAssert(maxTextureUnits > kNumStages);
199 }
200 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
201 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
202 GrAssert(maxTextureUnits > kNumStages);
203 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000204
reed@google.comac10a2d2010-12-22 21:39:39 +0000205 ////////////////////////////////////////////////////////////////////////////
206 // Check for supported features.
207
208 int major, minor;
209 gl_version(&major, &minor);
210
twiz@google.com0f31ca72011-03-18 17:38:11 +0000211 GrGLint numFormats;
212 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
213 GrAutoSTMalloc<10, GrGLint> formats(numFormats);
214 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000216 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000217 f8bitPaletteSupport = true;
218 break;
219 }
220 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000221
222 if (gPrintStartupSpew) {
223 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
224 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000225
226 GR_STATIC_ASSERT(0 == kNone_AALevel);
227 GR_STATIC_ASSERT(1 == kLow_AALevel);
228 GR_STATIC_ASSERT(2 == kMed_AALevel);
229 GR_STATIC_ASSERT(3 == kHigh_AALevel);
230
231 memset(fAASamples, 0, sizeof(fAASamples));
232 fMSFBOType = kNone_MSFBO;
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000233 if (GR_GL_SUPPORT_ES) {
234 if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000235 // chrome's extension is equivalent to the EXT msaa
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000236 // and fbo_blit extensions.
237 fMSFBOType = kDesktopEXT_MSFBO;
238 } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
239 fMSFBOType = kAppleES_MSFBO;
240 }
241 } else {
242 GrAssert(GR_GL_SUPPORT_DESKTOP);
243 if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
244 fMSFBOType = kDesktopARB_MSFBO;
245 } else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
246 has_gl_extension("GL_EXT_framebuffer_blit")) {
247 fMSFBOType = kDesktopEXT_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000248 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000249 }
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000250 if (gPrintStartupSpew) {
251 switch (fMSFBOType) {
252 case kNone_MSFBO:
253 GrPrintf("MSAA Support: NONE\n");
254 break;
255 case kDesktopARB_MSFBO:
256 GrPrintf("MSAA Support: DESKTOP ARB.\n");
257 break;
258 case kDesktopEXT_MSFBO:
259 GrPrintf("MSAA Support: DESKTOP EXT.\n");
260 break;
261 case kAppleES_MSFBO:
262 GrPrintf("MSAA Support: APPLE ES.\n");
263 break;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000264 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000265 }
266
267 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000268 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000269 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000270 if (maxSamples > 1 ) {
271 fAASamples[kNone_AALevel] = 0;
272 fAASamples[kLow_AALevel] = GrMax(2,
273 GrFixedFloorToInt((GR_FixedHalf) *
274 maxSamples));
275 fAASamples[kMed_AALevel] = GrMax(2,
276 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
277 maxSamples));
278 fAASamples[kHigh_AALevel] = maxSamples;
279 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000280 if (gPrintStartupSpew) {
281 GrPrintf("\tMax Samples: %d\n", maxSamples);
282 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000283 }
284
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000285 if (GR_GL_SUPPORT_DESKTOP) {
286 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
287 has_gl_extension("GL_EXT_stencil_wrap");
288 } else {
289 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
290 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000291 if (gPrintStartupSpew) {
292 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
293 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000294
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000295 if (GR_GL_SUPPORT_DESKTOP) {
296 // we could also look for GL_ATI_separate_stencil extension or
297 // GL_EXT_stencil_two_side but they use different function signatures
298 // than GL2.0+ (and than each other).
299 fTwoSidedStencilSupport = (major >= 2);
300 // supported on GL 1.4 and higher or by extension
301 fStencilWrapOpsSupport = (major > 1) ||
302 ((1 == major) && (minor >= 4)) ||
303 has_gl_extension("GL_EXT_stencil_wrap");
304 } else {
305 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
306 // an ES1 extension.
307 fTwoSidedStencilSupport = (major >= 2);
308 // stencil wrap support is in ES2, ES1 requires extension.
309 fStencilWrapOpsSupport = (major > 1) ||
310 has_gl_extension("GL_OES_stencil_wrap");
311 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000312 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000313 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
314 (fTwoSidedStencilSupport ? "YES" : "NO"),
315 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000316 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000317
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000318 if (GR_GL_SUPPORT_DESKTOP) {
319 fRGBA8Renderbuffer = true;
320 } else {
321 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
322 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000323 if (gPrintStartupSpew) {
324 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
325 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000326
327
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000328 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000329 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000330 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
331 }
332 }
333
334 if (GR_GL_SUPPORT_DESKTOP) {
335 fBufferLockSupport = true; // we require VBO support and the desktop VBO
336 // extension includes glMapBuffer.
337 } else {
338 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
339 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000340
reed@google.comeeeb5a02010-12-23 15:12:59 +0000341 if (gPrintStartupSpew) {
342 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
343 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000344
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000345 if (GR_GL_SUPPORT_DESKTOP) {
346 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
347 fNPOTTextureTileSupport = true;
348 fNPOTTextureSupport = true;
349 } else {
350 fNPOTTextureTileSupport = false;
351 fNPOTTextureSupport = false;
352 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000353 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000354 if (major >= 2) {
355 fNPOTTextureSupport = true;
356 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
357 } else {
358 fNPOTTextureSupport =
359 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
360 fNPOTTextureTileSupport = false;
361 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000362 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000363
reed@google.comac10a2d2010-12-22 21:39:39 +0000364 ////////////////////////////////////////////////////////////////////////////
365 // Experiments to determine limitations that can't be queried. TODO: Make
366 // these a preprocess that generate some compile time constants.
367
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000368 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000369
twiz@google.com59a190b2011-03-14 21:23:01 +0000370 bool simpleFBOSuccess = fbo_test(128, 128);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000371 if (gPrintStartupSpew) {
372 if (!simpleFBOSuccess) {
373 GrPrintf("FBO Sanity Test: FAILED\n");
374 } else {
375 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000376 }
377 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000378 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000379
reed@google.comac10a2d2010-12-22 21:39:39 +0000380 /* Experimentation has found that some GLs that support NPOT textures
381 do not support FBOs with a NPOT texture. They report "unsupported" FBO
382 status. I don't know how to explicitly query for this. Do an
383 experiment. Note they may support NPOT with a renderbuffer but not a
384 texture. Presumably, the implementation bloats the renderbuffer
385 internally to the next POT.
386 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000387 bool fNPOTRenderTargetSupport = false;
388 if (fNPOTTextureSupport) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000389 fNPOTRenderTargetSupport = fbo_test(200, 200);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000390 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000391
bsalomon@google.com0748f212011-02-01 22:56:16 +0000392 if (gPrintStartupSpew) {
393 if (fNPOTTextureSupport) {
394 GrPrintf("NPOT textures supported\n");
395 if (fNPOTTextureTileSupport) {
396 GrPrintf("NPOT texture tiling supported\n");
397 } else {
398 GrPrintf("NPOT texture tiling NOT supported\n");
399 }
400 if (fNPOTRenderTargetSupport) {
401 GrPrintf("NPOT render targets supported\n");
402 } else {
403 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000404 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000405 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000406 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000407 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000408 }
409
reed@google.comac10a2d2010-12-22 21:39:39 +0000410 /* The iPhone 4 has a restriction that for an FBO with texture color
411 attachment with height <= 8 then the width must be <= height. Here
412 we look for such a limitation.
413 */
414 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000415 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000416 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000417
reed@google.comeeeb5a02010-12-23 15:12:59 +0000418 if (gPrintStartupSpew) {
419 GrPrintf("Small height FBO texture experiments\n");
420 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000421
twiz@google.com0f31ca72011-03-18 17:38:11 +0000422 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
423 GrGLuint w = maxRenderSize;
424 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000425 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000426 if (gPrintStartupSpew) {
427 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
428 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000429 fMinRenderTargetHeight = i;
430 break;
431 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000432 if (gPrintStartupSpew) {
433 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
434 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000435 }
436 }
437 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
438
reed@google.comeeeb5a02010-12-23 15:12:59 +0000439 if (gPrintStartupSpew) {
440 GrPrintf("Small width FBO texture experiments\n");
441 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000442 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000443 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
444 GrGLuint w = i;
445 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000446 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000447 if (gPrintStartupSpew) {
448 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
449 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000450 fMinRenderTargetWidth = i;
451 break;
452 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000453 if (gPrintStartupSpew) {
454 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
455 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000456 }
457 }
458 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
459
twiz@google.com0f31ca72011-03-18 17:38:11 +0000460 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000461}
462
463GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000464}
465
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000466void GrGpuGL::resetContext() {
467 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000468 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000469 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000470
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000471 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000472 GR_GL(Disable(GR_GL_DEPTH_TEST));
473 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000474
twiz@google.com0f31ca72011-03-18 17:38:11 +0000475 GR_GL(Disable(GR_GL_CULL_FACE));
476 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000477 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000478
twiz@google.com0f31ca72011-03-18 17:38:11 +0000479 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000480 if (GR_GL_SUPPORT_DESKTOP) {
481 GR_GL(Disable(GR_GL_LINE_SMOOTH));
482 GR_GL(Disable(GR_GL_POINT_SMOOTH));
483 GR_GL(Disable(GR_GL_MULTISAMPLE));
484 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000485
twiz@google.com0f31ca72011-03-18 17:38:11 +0000486 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000487 fHWDrawState.fFlagBits = 0;
488
reed@google.comac10a2d2010-12-22 21:39:39 +0000489 // we only ever use lines in hairline mode
490 GR_GL(LineWidth(1));
491
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000492 // invalid
493 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000494
reed@google.comac10a2d2010-12-22 21:39:39 +0000495 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000496 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
497 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000498
499 fHWDrawState.fBlendConstant = 0x00000000;
500 GR_GL(BlendColor(0,0,0,0));
501
reed@google.comac10a2d2010-12-22 21:39:39 +0000502 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000503
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000504 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000505
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000506 for (int s = 0; s < kNumStages; ++s) {
507 fHWDrawState.fTextures[s] = NULL;
508 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
509 -GR_ScalarMax,
510 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000511
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000512 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000513 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000514
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000515 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000516 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000517 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000518 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000519
bsalomon@google.comd302f142011-03-03 13:54:13 +0000520 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000521 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000522 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000523
524 fHWGeometryState.fIndexBuffer = NULL;
525 fHWGeometryState.fVertexBuffer = NULL;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000526 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
527 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000528 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000529
twiz@google.com0f31ca72011-03-18 17:38:11 +0000530 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000531 fHWDrawState.fRenderTarget = NULL;
532}
533
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000534GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
reed@google.comac10a2d2010-12-22 21:39:39 +0000535 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000536 int stencilBits,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000537 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000538 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000539 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
540 rtIDs.fStencilRenderbufferID = 0;
541 rtIDs.fMSColorRenderbufferID = 0;
542 rtIDs.fTexFBOID = 0;
543 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000544 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000545
546 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000547 viewport.fLeft = 0;
548 viewport.fBottom = 0;
549 viewport.fWidth = width;
550 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000551
twiz@google.com0f31ca72011-03-18 17:38:11 +0000552 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
553 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000554
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000555 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000556}
557
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000558GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000559
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000560 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000561
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000562 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000563 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
564 rtIDs.fMSColorRenderbufferID = 0;
565 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000566
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000567 GrGLIRect viewport;
568 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000569 GrGLuint stencilBits;
570 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000571
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000572 rtIDs.fOwnIDs = false;
573
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000574 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000575}
576
bsalomon@google.com5782d712011-01-21 21:03:59 +0000577///////////////////////////////////////////////////////////////////////////////
578
twiz@google.com0f31ca72011-03-18 17:38:11 +0000579static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000580
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000581struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000582 GrGLenum fEnum;
583 GrGLuint fBits;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000584};
585
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000586const StencilFormat* GrGLStencilFormats() {
587 // defines stencil formats from more to less preferred
588 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000589 {GR_GL_STENCIL_INDEX8, 8},
590 {GR_GL_STENCIL_INDEX16, 16},
591 {GR_GL_DEPTH24_STENCIL8, 8},
592 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000593 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS},
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000594 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000595 {0, 0}
596 };
597
598 static const StencilFormat esStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000599 {GR_GL_STENCIL_INDEX8, 8},
600 {GR_GL_DEPTH24_STENCIL8, 8},
601 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000602 {0, 0}
603 };
604
605 if (GR_GL_SUPPORT_DESKTOP) {
606 return desktopStencilFormats;
607 } else {
608 return esStencilFormats;
609 }
610}
611
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000612// good to set a break-point here to know when createTexture fails
613static GrTexture* return_null_texture() {
614// GrAssert(!"null texture");
615 return NULL;
616}
617
618#if GR_DEBUG
619static size_t as_size_t(int x) {
620 return x;
621}
622#endif
623
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000624GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
625 const void* srcData,
626 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000627
628#if GR_COLLECT_STATS
629 ++fStats.fTextureCreateCnt;
630#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000631
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000632 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000633
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000634 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000635 GR_GL_NEAREST,
636 GR_GL_CLAMP_TO_EDGE,
637 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000638 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000639
reed@google.comac10a2d2010-12-22 21:39:39 +0000640 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000641 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000642
643 glDesc.fContentWidth = desc.fWidth;
644 glDesc.fContentHeight = desc.fHeight;
645 glDesc.fAllocWidth = desc.fWidth;
646 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000647 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000648 glDesc.fFormat = desc.fFormat;
649
650 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
651 if (!canBeTexture(desc.fFormat,
652 &internalFormat,
653 &glDesc.fUploadFormat,
654 &glDesc.fUploadType)) {
655 return return_null_texture();
656 }
657
658 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000659 GrGLint samples = fAASamples[desc.fAALevel];
reed@google.comac10a2d2010-12-22 21:39:39 +0000660 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
661 GrPrintf("AA RT requested but not supported on this platform.");
662 }
663
664 GR_GL(GenTextures(1, &glDesc.fTextureID));
665 if (!glDesc.fTextureID) {
666 return return_null_texture();
667 }
668
669 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
670
671 /*
672 * check if our srcData has extra bytes past each row. If so, we need
673 * to trim those off here, since GL doesn't let us pass the rowBytes as
674 * a parameter to glTexImage2D
675 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000676 if (GR_GL_SUPPORT_DESKTOP) {
677 if (srcData) {
678 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
679 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000680 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000681 } else {
682 GrAutoSMalloc<128 * 128> trimStorage;
683 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
684 if (srcData && (trimRowBytes < rowBytes)) {
685 size_t trimSize = desc.fHeight * trimRowBytes;
686 trimStorage.realloc(trimSize);
687 // now copy the data into our new storage, skipping the trailing bytes
688 const char* src = (const char*)srcData;
689 char* dst = (char*)trimStorage.get();
690 for (uint32_t y = 0; y < desc.fHeight; y++) {
691 memcpy(dst, src, trimRowBytes);
692 src += rowBytes;
693 dst += trimRowBytes;
694 }
695 // now point srcData to our trimmed version
696 srcData = trimStorage.get();
697 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000698 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000699
reed@google.comac10a2d2010-12-22 21:39:39 +0000700 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000701 if (!this->npotRenderTargetSupport()) {
702 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
703 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
704 }
705
reed@google.comac10a2d2010-12-22 21:39:39 +0000706 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
707 glDesc.fAllocWidth);
708 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
709 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000710 } else if (!this->npotTextureSupport()) {
711 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
712 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000713 }
714
twiz@google.com0f31ca72011-03-18 17:38:11 +0000715 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
716 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
717 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000718 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000719 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
720 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000721 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000722 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
723 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000724 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000725 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
726 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000727 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000728
twiz@google.com0f31ca72011-03-18 17:38:11 +0000729 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000730 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
731 supports8BitPalette()) {
732 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
733 GrAssert(desc.fWidth == glDesc.fAllocWidth);
734 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000735 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
736 kColorTableSize;
737 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000738 glDesc.fAllocWidth, glDesc.fAllocHeight,
739 0, imageSize, srcData));
740 GrGL_RestoreResetRowLength();
741 } else {
742 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
743 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000744 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000745 glDesc.fAllocWidth, glDesc.fAllocHeight,
746 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000747 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000748 desc.fHeight, glDesc.fUploadFormat,
749 glDesc.fUploadType, srcData));
750 GrGL_RestoreResetRowLength();
751
752 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
753 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
754 uint32_t maxTexels = extraW * extraH;
755 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
756 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
757
758 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
759
760 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
761 if (extraH) {
762 uint8_t* lastRowStart = (uint8_t*) srcData +
763 (desc.fHeight - 1) * rowSize;
764 uint8_t* extraRowStart = (uint8_t*)texels.get();
765
766 for (uint32_t i = 0; i < extraH; ++i) {
767 memcpy(extraRowStart, lastRowStart, rowSize);
768 extraRowStart += rowSize;
769 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000770 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000771 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
772 texels.get()));
773 }
774 if (extraW) {
775 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
776 uint8_t* extraTexel = (uint8_t*)texels.get();
777 for (uint32_t j = 0; j < desc.fHeight; ++j) {
778 for (uint32_t i = 0; i < extraW; ++i) {
779 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
780 extraTexel += glDesc.fUploadByteCount;
781 }
782 edgeTexel += rowSize;
783 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000784 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000785 desc.fHeight, glDesc.fUploadFormat,
786 glDesc.fUploadType, texels.get()));
787 }
788 if (extraW && extraH) {
789 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
790 - glDesc.fUploadByteCount;
791 uint8_t* extraTexel = (uint8_t*)texels.get();
792 for (uint32_t i = 0; i < extraW*extraH; ++i) {
793 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
794 extraTexel += glDesc.fUploadByteCount;
795 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000796 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000797 extraW, extraH, glDesc.fUploadFormat,
798 glDesc.fUploadType, texels.get()));
799 }
800
801 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000802 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000803 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
804 glDesc.fUploadType, srcData));
805 GrGL_RestoreResetRowLength();
806 }
807 }
808
809 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
810
811 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
812 rtIDs.fStencilRenderbufferID = 0;
813 rtIDs.fMSColorRenderbufferID = 0;
814 rtIDs.fRTFBOID = 0;
815 rtIDs.fTexFBOID = 0;
816 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000817 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000818
819 if (renderTarget) {
820#if GR_COLLECT_STATS
821 ++fStats.fRenderTargetCreateCnt;
822#endif
823 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000824 GrGLenum status;
825 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000826
827 // If need have both RT flag and srcData we have
828 // to invert the data before uploading because FBO
829 // will be rendered bottom up
830 GrAssert(NULL == srcData);
831 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
832
twiz@google.com59a190b2011-03-14 21:23:01 +0000833 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000834 GrAssert(rtIDs.fTexFBOID);
835
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000836 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000837 // to one and then resolve to the texture bound to the other.
838 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000839 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000840 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000841 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000842 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
843 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000844 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000845 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000846 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
847 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000848 return return_null_texture();
849 }
850 } else {
851 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
852 }
bsalomon@google.comf6a7c112011-03-24 16:14:10 +0000853 if (!(kNoStencil_TextureFlag & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000854 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000855 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000856 }
857
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000858 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000859 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000860 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000861 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000862
twiz@google.com0f31ca72011-03-18 17:38:11 +0000863 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000864
865 const StencilFormat* stencilFormats = GrGLStencilFormats();
866 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000867 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000868 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000869 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000870 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000871 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000872 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000873 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000874 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000875 glDesc.fAllocWidth,
876 glDesc.fAllocHeight));
877 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000878 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000879 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000880 glDesc.fAllocWidth,
881 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000882 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000883 err = GrGLGetGLInterface()->fGetError();
884 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000885 continue;
886 }
887 }
888 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
889 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000890 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000891 rtIDs.fMSColorRenderbufferID));
892 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000893 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000894 samples,
895 msColorRenderbufferFormat,
896 glDesc.fAllocWidth,
897 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000898 err = GrGLGetGLInterface()->fGetError();
899 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000900 continue;
901 }
902 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000903 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000904
905#if GR_COLLECT_STATS
906 ++fStats.fRenderTargetChngCnt;
907#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000908 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
909 GR_GL_COLOR_ATTACHMENT0,
910 GR_GL_TEXTURE_2D,
911 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000912 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000913 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
914 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000915 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
916 status, desc.fWidth, desc.fHeight);
917 continue;
918 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000919 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000920 #if GR_COLLECT_STATS
921 ++fStats.fRenderTargetChngCnt;
922 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000923 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
924 GR_GL_COLOR_ATTACHMENT0,
925 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000926 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000927
928 }
929 if (rtIDs.fStencilRenderbufferID) {
930 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000931 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
932 GR_GL_STENCIL_ATTACHMENT,
933 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000934 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000935 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000936 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000937
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000938 if (GR_GL_SUPPORT_DESKTOP) {
939 // On some implementations you have to be bound as DEPTH_STENCIL.
940 // (Even binding to DEPTH and STENCIL separately with the same
941 // buffer doesn't work.)
942 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000943 status != GR_GL_FRAMEBUFFER_COMPLETE) {
944 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
945 GR_GL_STENCIL_ATTACHMENT,
946 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000947 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000948 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
949 GR_GL_DEPTH_STENCIL_ATTACHMENT,
950 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000951 rtIDs.fStencilRenderbufferID));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000952 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000953 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000954 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000955 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000956 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
957 status, desc.fWidth, desc.fHeight);
958 if (GR_GL_SUPPORT_DESKTOP) {
959 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000960 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
961 GR_GL_DEPTH_STENCIL_ATTACHMENT,
962 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000963 0));
964 }
965 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000966 continue;
967 }
968 // we're successful!
969 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000970 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000971 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000972 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000973 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000974 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000975 }
976 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000977 break;
978 }
979 if (failed) {
980 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000981 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000982 }
983 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000984 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000985 }
986 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000987 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000988 }
989 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000990 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000991 }
992 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
993 return return_null_texture();
994 }
995 }
996#ifdef TRACE_TEXTURE_CREATION
997 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
998 tex->fTextureID, width, height, tex->fUploadByteCount);
999#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001000 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001001
1002 if (0 != rtIDs.fTexFBOID) {
1003 GrRenderTarget* rt = tex->asRenderTarget();
1004 // We've messed with FBO state but may not have set the correct viewport
1005 // so just dirty the rendertarget state to force a resend.
1006 fHWDrawState.fRenderTarget = NULL;
1007
1008 // clear the new stencil buffer if we have one
bsalomon@google.comf6a7c112011-03-24 16:14:10 +00001009 if (!(desc.fFlags & kNoStencil_TextureFlag)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001010 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1011 fCurrDrawState.fRenderTarget = rt;
1012 eraseStencil(0, ~0);
1013 fCurrDrawState.fRenderTarget = rtSave;
1014 }
1015 }
1016 return tex;
1017}
1018
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001019GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001020 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001021 GR_GL(GenBuffers(1, &id));
1022 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001023 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001024 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001025 GrGLClearErr();
1026 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001027 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1028 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1029 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001030 GR_GL(DeleteBuffers(1, &id));
1031 // deleting bound buffer does implicit bind to 0
1032 fHWGeometryState.fVertexBuffer = NULL;
1033 return NULL;
1034 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001035 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001036 size, dynamic);
1037 fHWGeometryState.fVertexBuffer = vertexBuffer;
1038 return vertexBuffer;
1039 }
1040 return NULL;
1041}
1042
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001043GrIndexBuffer* GrGpuGL::createIndexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001044 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001045 GR_GL(GenBuffers(1, &id));
1046 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001047 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001048 GrGLClearErr();
1049 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001050 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1051 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1052 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001053 GR_GL(DeleteBuffers(1, &id));
1054 // deleting bound buffer does implicit bind to 0
1055 fHWGeometryState.fIndexBuffer = NULL;
1056 return NULL;
1057 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001058 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001059 size, dynamic);
1060 fHWGeometryState.fIndexBuffer = indexBuffer;
1061 return indexBuffer;
1062 }
1063 return NULL;
1064}
1065
reed@google.comac10a2d2010-12-22 21:39:39 +00001066void GrGpuGL::flushScissor(const GrIRect* rect) {
1067 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001068 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001069 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001070
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001071 GrGLIRect scissor;
1072 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001073 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001074 rect->width(), rect->height());
1075 if (scissor.contains(vp)) {
1076 rect = NULL;
1077 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001078 }
1079
1080 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001081 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001082 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001083 fHWBounds.fScissorRect = scissor;
1084 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001085 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001086 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001087 fHWBounds.fScissorEnabled = true;
1088 }
1089 } else {
1090 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001091 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001092 fHWBounds.fScissorEnabled = false;
1093 }
1094 }
1095}
1096
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001097void GrGpuGL::eraseColorHelper(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001098 if (NULL == fCurrDrawState.fRenderTarget) {
1099 return;
1100 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001101 flushRenderTarget();
1102 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001103 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001104 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001105 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001106 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001107 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001108 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1109 GrColorUnpackG(color)/255.f,
1110 GrColorUnpackB(color)/255.f,
1111 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001112 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001113}
1114
1115void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001116 if (NULL == fCurrDrawState.fRenderTarget) {
1117 return;
1118 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001119 flushRenderTarget();
1120 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001121 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001122 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001123 }
1124 GR_GL(StencilMask(mask));
1125 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001126 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001127 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001128}
1129
bsalomon@google.comd302f142011-03-03 13:54:13 +00001130void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001131 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001132#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001133 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001134 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001135 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001136#else
1137 // we could just clear the clip bit but when we go through
1138 // angle a partial stencil mask will cause clears to be
1139 // turned into draws. Our contract on GrDrawTarget says that
1140 // changing the clip between stencil passes may or may not
1141 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001142 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001143#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001144 flushRenderTarget();
1145 flushScissor(&rect);
1146 GR_GL(StencilMask(clipStencilMask));
1147 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001148 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001149 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001150}
1151
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001152void GrGpuGL::forceRenderTargetFlushHelper() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001153 flushRenderTarget();
1154}
1155
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001156bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height,
1157 GrTexture::PixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001158 GrGLenum internalFormat; // we don't use this for glReadPixels
1159 GrGLenum format;
1160 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001161 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1162 return false;
1163 }
1164
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001165 if (NULL == fCurrDrawState.fRenderTarget) {
1166 return false;
1167 }
1168 flushRenderTarget();
1169
bsalomon@google.comd302f142011-03-03 13:54:13 +00001170 const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
1171
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001172 // the read rect is viewport-relative
1173 GrGLIRect readRect;
1174 readRect.setRelativeTo(glvp, left, top, width, height);
1175 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001176 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001177 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001178
1179 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1180 // API presents top-to-bottom
1181 {
1182 size_t stride = width * GrTexture::BytesPerPixel(config);
1183 GrAutoMalloc rowStorage(stride);
1184 void* tmp = rowStorage.get();
1185
1186 const int halfY = height >> 1;
1187 char* top = reinterpret_cast<char*>(buffer);
1188 char* bottom = top + (height - 1) * stride;
1189 for (int y = 0; y < halfY; y++) {
1190 memcpy(tmp, top, stride);
1191 memcpy(top, bottom, stride);
1192 memcpy(bottom, tmp, stride);
1193 top += stride;
1194 bottom -= stride;
1195 }
1196 }
1197 return true;
1198}
1199
1200void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001201
1202 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1203
reed@google.comac10a2d2010-12-22 21:39:39 +00001204 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1205 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001206 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001207 #if GR_COLLECT_STATS
1208 ++fStats.fRenderTargetChngCnt;
1209 #endif
1210 rt->setDirty(true);
1211 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001212 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1213 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001214 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1215 }
1216 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001217 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001218 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001219 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001220 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001221 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001222 fHWBounds.fViewportRect = vp;
1223 }
1224 }
1225}
1226
twiz@google.com0f31ca72011-03-18 17:38:11 +00001227GrGLenum gPrimitiveType2GLMode[] = {
1228 GR_GL_TRIANGLES,
1229 GR_GL_TRIANGLE_STRIP,
1230 GR_GL_TRIANGLE_FAN,
1231 GR_GL_POINTS,
1232 GR_GL_LINES,
1233 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001234};
1235
bsalomon@google.comd302f142011-03-03 13:54:13 +00001236#define SWAP_PER_DRAW 0
1237
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001238#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001239 #if GR_MAC_BUILD
1240 #include <AGL/agl.h>
1241 #elif GR_WIN32_BUILD
1242 void SwapBuf() {
1243 DWORD procID = GetCurrentProcessId();
1244 HWND hwnd = GetTopWindow(GetDesktopWindow());
1245 while(hwnd) {
1246 DWORD wndProcID = 0;
1247 GetWindowThreadProcessId(hwnd, &wndProcID);
1248 if(wndProcID == procID) {
1249 SwapBuffers(GetDC(hwnd));
1250 }
1251 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1252 }
1253 }
1254 #endif
1255#endif
1256
bsalomon@google.comffca4002011-02-22 20:34:01 +00001257void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001258 uint32_t startVertex,
1259 uint32_t startIndex,
1260 uint32_t vertexCount,
1261 uint32_t indexCount) {
1262 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1263
twiz@google.com0f31ca72011-03-18 17:38:11 +00001264 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001265
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001266 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1267 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1268
1269 // our setupGeometry better have adjusted this to zero since
1270 // DrawElements always draws from the begining of the arrays for idx 0.
1271 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001272
1273 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001274 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001275#if SWAP_PER_DRAW
1276 glFlush();
1277 #if GR_MAC_BUILD
1278 aglSwapBuffers(aglGetCurrentContext());
1279 int set_a_break_pt_here = 9;
1280 aglSwapBuffers(aglGetCurrentContext());
1281 #elif GR_WIN32_BUILD
1282 SwapBuf();
1283 int set_a_break_pt_here = 9;
1284 SwapBuf();
1285 #endif
1286#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001287}
1288
bsalomon@google.comffca4002011-02-22 20:34:01 +00001289void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001290 uint32_t startVertex,
1291 uint32_t vertexCount) {
1292 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1293
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001294 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1295
1296 // our setupGeometry better have adjusted this to zero.
1297 // DrawElements doesn't take an offset so we always adjus the startVertex.
1298 GrAssert(0 == startVertex);
1299
1300 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1301 // account for startVertex in the DrawElements case. So we always
1302 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001303 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001304#if SWAP_PER_DRAW
1305 glFlush();
1306 #if GR_MAC_BUILD
1307 aglSwapBuffers(aglGetCurrentContext());
1308 int set_a_break_pt_here = 9;
1309 aglSwapBuffers(aglGetCurrentContext());
1310 #elif GR_WIN32_BUILD
1311 SwapBuf();
1312 int set_a_break_pt_here = 9;
1313 SwapBuf();
1314 #endif
1315#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001316}
1317
reed@google.comac10a2d2010-12-22 21:39:39 +00001318void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1319 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1320
1321 if (NULL != rt && rt->needsResolve()) {
1322 GrAssert(kNone_MSFBO != fMSFBOType);
1323 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001324 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001325 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001326 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001327 rt->textureFBOID()));
1328 #if GR_COLLECT_STATS
1329 ++fStats.fRenderTargetChngCnt;
1330 #endif
1331 // make sure we go through set render target
1332 fHWDrawState.fRenderTarget = NULL;
1333
twiz@google.com0f31ca72011-03-18 17:38:11 +00001334 GrGLint left = 0;
1335 GrGLint right = texture->width();
reed@google.comac10a2d2010-12-22 21:39:39 +00001336 // we will have rendered to the top of the FBO.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001337 GrGLint top = texture->allocHeight();
1338 GrGLint bottom = texture->allocHeight() - texture->height();
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001339 if (kAppleES_MSFBO == fMSFBOType) {
1340 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001341 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001342 GR_GL(Scissor(left, bottom, right-left, top-bottom));
twiz@google.com59a190b2011-03-14 21:23:01 +00001343 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001344 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001345 fHWBounds.fScissorEnabled = true;
1346 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001347 if (kDesktopARB_MSFBO != fMSFBOType) {
1348 // these respect the scissor during the blit, so disable it.
1349 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1350 flushScissor(NULL);
1351 }
twiz@google.com59a190b2011-03-14 21:23:01 +00001352 GR_GL(BlitFramebuffer(left, bottom, right, top,
reed@google.comac10a2d2010-12-22 21:39:39 +00001353 left, bottom, right, top,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001354 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001355 }
1356 rt->setDirty(false);
reed@google.comac10a2d2010-12-22 21:39:39 +00001357 }
1358}
1359
twiz@google.com0f31ca72011-03-18 17:38:11 +00001360static const GrGLenum grToGLStencilFunc[] = {
1361 GR_GL_ALWAYS, // kAlways_StencilFunc
1362 GR_GL_NEVER, // kNever_StencilFunc
1363 GR_GL_GREATER, // kGreater_StencilFunc
1364 GR_GL_GEQUAL, // kGEqual_StencilFunc
1365 GR_GL_LESS, // kLess_StencilFunc
1366 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1367 GR_GL_EQUAL, // kEqual_StencilFunc,
1368 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001369};
1370GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1371GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1372GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1373GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1374GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1375GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1376GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1377GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1378GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1379
twiz@google.com0f31ca72011-03-18 17:38:11 +00001380static const GrGLenum grToGLStencilOp[] = {
1381 GR_GL_KEEP, // kKeep_StencilOp
1382 GR_GL_REPLACE, // kReplace_StencilOp
1383 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1384 GR_GL_INCR, // kIncClamp_StencilOp
1385 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1386 GR_GL_DECR, // kDecClamp_StencilOp
1387 GR_GL_ZERO, // kZero_StencilOp
1388 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001389};
1390GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1391GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1392GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1393GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1394GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1395GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1396GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1397GR_STATIC_ASSERT(6 == kZero_StencilOp);
1398GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1399
reed@google.comac10a2d2010-12-22 21:39:39 +00001400void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001401 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001402
1403 // use stencil for clipping if clipping is enabled and the clip
1404 // has been written into the stencil.
1405 bool stencilClip = fClipState.fClipInStencil &&
1406 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001407 bool stencilChange = fHWStencilClip != stencilClip ||
1408 fHWDrawState.fStencilSettings != *settings ||
1409 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1410 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001411
1412 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001413
bsalomon@google.comd302f142011-03-03 13:54:13 +00001414 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1415 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001416
bsalomon@google.comd302f142011-03-03 13:54:13 +00001417 if (settings->isDisabled()) {
1418 if (stencilClip) {
1419 settings = &gClipStencilSettings;
1420 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001421 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001422
1423 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001424 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001425 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001426 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001427 #if GR_DEBUG
1428 if (!fStencilWrapOpsSupport) {
1429 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1430 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1431 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1432 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1433 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1434 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1435 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1436 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1437 }
1438 #endif
1439 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1440 GrAssert(stencilBits ||
1441 (GrStencilSettings::gDisabled ==
1442 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001443 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1444 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001445
1446 unsigned int frontRef = settings->fFrontFuncRef;
1447 unsigned int frontMask = settings->fFrontFuncMask;
1448 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001449 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001450
1451 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1452
1453 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1454 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1455 } else {
1456 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1457
1458 ConvertStencilFuncAndMask(settings->fFrontFunc,
1459 stencilClip,
1460 clipStencilMask,
1461 userStencilMask,
1462 &frontRef,
1463 &frontMask);
1464 frontWriteMask &= userStencilMask;
1465 }
1466 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001467 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001468 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001469 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001470 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001471 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001472 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001473 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001474 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001475 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001476
1477 unsigned int backRef = settings->fBackFuncRef;
1478 unsigned int backMask = settings->fBackFuncMask;
1479 unsigned int backWriteMask = settings->fBackWriteMask;
1480
1481
1482 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1483 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1484 backFunc = grToGLStencilFunc[settings->fBackFunc];
1485 } else {
1486 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1487 ConvertStencilFuncAndMask(settings->fBackFunc,
1488 stencilClip,
1489 clipStencilMask,
1490 userStencilMask,
1491 &backRef,
1492 &backMask);
1493 backWriteMask &= userStencilMask;
1494 }
1495
twiz@google.com0f31ca72011-03-18 17:38:11 +00001496 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1497 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1498 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1499 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1500 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001501 grToGLStencilOp[settings->fFrontPassOp],
1502 grToGLStencilOp[settings->fFrontPassOp]));
1503
twiz@google.com0f31ca72011-03-18 17:38:11 +00001504 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001505 grToGLStencilOp[settings->fBackPassOp],
1506 grToGLStencilOp[settings->fBackPassOp]));
1507 } else {
1508 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1509 GR_GL(StencilMask(frontWriteMask));
1510 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1511 grToGLStencilOp[settings->fFrontPassOp],
1512 grToGLStencilOp[settings->fFrontPassOp]));
1513 }
1514 }
1515 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001516 fHWStencilClip = stencilClip;
1517 }
1518}
1519
bsalomon@google.comffca4002011-02-22 20:34:01 +00001520bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001521
1522 // GrGpu::setupClipAndFlushState should have already checked this
1523 // and bailed if not true.
1524 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001525
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001526 for (int s = 0; s < kNumStages; ++s) {
1527 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001528
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001529 // bind texture and set sampler state
1530 if (usingTexture) {
1531 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001532
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001533 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001534 // if we created a rt/tex and rendered to it without using a
1535 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001536 // the last bound texture, but it needs resolving. So keep this
1537 // out of the "last != next" check.
1538 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001539
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001540 if (fHWDrawState.fTextures[s] != nextTexture) {
1541 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001542 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001543 #if GR_COLLECT_STATS
1544 ++fStats.fTextureChngCnt;
1545 #endif
1546 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1547 fHWDrawState.fTextures[s] = nextTexture;
1548 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001549
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001550 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001551 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001552 nextTexture->getTexParams();
1553 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001554
twiz@google.com0f31ca72011-03-18 17:38:11 +00001555 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1556 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001557 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001558 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001559 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001560 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001561
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001562 if (newTexParams.fFilter != oldTexParams.fFilter) {
1563 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001564 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1565 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001566 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001567 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1568 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001569 newTexParams.fFilter));
1570 }
1571 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1572 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001573 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1574 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001575 newTexParams.fWrapS));
1576 }
1577 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1578 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001579 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1580 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001581 newTexParams.fWrapT));
1582 }
1583 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001584
1585 // The texture matrix has to compensate for texture width/height
1586 // and NPOT-embedded-in-POT
1587 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001588 } else {
1589 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001590 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001591 }
1592 }
1593 }
1594
1595 flushRenderTarget();
1596
1597 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1598 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1599 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001600 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001601 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001602 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001603 }
1604 }
1605
bsalomon@google.comd302f142011-03-03 13:54:13 +00001606 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1607 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001608 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001609 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001610 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001611 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001612 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001613 }
1614 GR_GL(ColorMask(mask, mask, mask, mask));
1615 }
1616
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001617 if (GR_GL_SUPPORT_DESKTOP) {
1618 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1619 // smooth lines.
1620 if (fDirtyFlags.fRenderTargetChanged ||
1621 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1622 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1623 GrGLint msaa = 0;
1624 // only perform query if we know MSAA is supported.
1625 // calling on non-MSAA target caused a crash in one environment,
1626 // though I don't think it should.
1627 if (fAASamples[kHigh_AALevel]) {
1628 GR_GL_GetIntegerv(GR_GL_SAMPLE_BUFFERS, &msaa);
1629 }
1630 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1631 if (msaa) {
1632 GR_GL(Enable(GR_GL_MULTISAMPLE));
1633 } else {
1634 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1635 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001636 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001637 if (msaa) {
1638 GR_GL(Disable(GR_GL_MULTISAMPLE));
1639 }
1640 GR_GL(Disable(GR_GL_LINE_SMOOTH));
reed@google.comac10a2d2010-12-22 21:39:39 +00001641 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001642 }
1643 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001644
1645 bool blendOff = canDisableBlend();
1646 if (fHWBlendDisabled != blendOff) {
1647 if (blendOff) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001648 GR_GL(Disable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001649 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001650 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001651 }
1652 fHWBlendDisabled = blendOff;
1653 }
1654
1655 if (!blendOff) {
1656 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1657 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1658 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1659 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1660 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1661 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1662 }
bsalomon@google.com080773c2011-03-15 19:09:25 +00001663 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1664 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1665 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1666
1667 float c[] = {
1668 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1669 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1670 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1671 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1672 };
1673 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1674 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1675 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001676 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001677
bsalomon@google.comd302f142011-03-03 13:54:13 +00001678 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1679 switch (fCurrDrawState.fDrawFace) {
1680 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001681 GR_GL(Enable(GR_GL_CULL_FACE));
1682 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001683 break;
1684 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001685 GR_GL(Enable(GR_GL_CULL_FACE));
1686 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001687 break;
1688 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001689 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001690 break;
1691 default:
1692 GrCrash("Unknown draw face.");
1693 }
1694 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1695 }
1696
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001697#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001698 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001699 for (int s = 0; s < kNumStages; ++s) {
1700 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1701 NULL == fCurrDrawState.fRenderTarget ||
1702 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001703 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001704 fCurrDrawState.fRenderTarget);
1705 }
1706#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001707
reed@google.comac10a2d2010-12-22 21:39:39 +00001708 flushStencil();
1709
bsalomon@google.comd302f142011-03-03 13:54:13 +00001710 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001711 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001712 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001713}
1714
1715void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001716 if (fHWGeometryState.fVertexBuffer != buffer) {
1717 fHWGeometryState.fArrayPtrsDirty = true;
1718 fHWGeometryState.fVertexBuffer = buffer;
1719 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001720}
1721
1722void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1723 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1724 buffer == fGeometrySrc.fVertexBuffer));
1725
1726 if (fHWGeometryState.fVertexBuffer == buffer) {
1727 // deleting bound buffer does implied bind to 0
1728 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001729 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001730 }
1731}
1732
1733void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1734 fGeometrySrc.fIndexBuffer = buffer;
1735}
1736
1737void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1738 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1739 buffer == fGeometrySrc.fIndexBuffer));
1740
1741 if (fHWGeometryState.fIndexBuffer == buffer) {
1742 // deleting bound buffer does implied bind to 0
1743 fHWGeometryState.fIndexBuffer = NULL;
1744 }
1745}
1746
reed@google.comac10a2d2010-12-22 21:39:39 +00001747void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1748 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001749 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001750 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001751 }
1752 if (fHWDrawState.fRenderTarget == renderTarget) {
1753 fHWDrawState.fRenderTarget = NULL;
1754 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001755}
1756
1757void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001758 for (int s = 0; s < kNumStages; ++s) {
1759 if (fCurrDrawState.fTextures[s] == texture) {
1760 fCurrDrawState.fTextures[s] = NULL;
1761 }
1762 if (fHWDrawState.fTextures[s] == texture) {
1763 // deleting bound texture does implied bind to 0
1764 fHWDrawState.fTextures[s] = NULL;
1765 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001766 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001767}
1768
reed@google.comac10a2d2010-12-22 21:39:39 +00001769bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001770 GrGLenum* internalFormat,
1771 GrGLenum* format,
1772 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001773 switch (config) {
1774 case GrTexture::kRGBA_8888_PixelConfig:
1775 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001776 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001777 if (GR_GL_SUPPORT_ES) {
1778 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1779 // format for a BGRA is BGRA not RGBA (as on desktop)
1780 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1781 } else {
1782 *internalFormat = GR_GL_RGBA;
1783 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001784 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001785 break;
1786 case GrTexture::kRGB_565_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001787 *format = GR_GL_RGB;
1788 *internalFormat = GR_GL_RGB;
1789 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001790 break;
1791 case GrTexture::kRGBA_4444_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001792 *format = GR_GL_RGBA;
1793 *internalFormat = GR_GL_RGBA;
1794 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001795 break;
1796 case GrTexture::kIndex_8_PixelConfig:
1797 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001798 *format = GR_GL_PALETTE8_RGBA8;
1799 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001800 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001801 } else {
1802 return false;
1803 }
1804 break;
1805 case GrTexture::kAlpha_8_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001806 *format = GR_GL_ALPHA;
1807 *internalFormat = GR_GL_ALPHA;
1808 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001809 break;
1810 default:
1811 return false;
1812 }
1813 return true;
1814}
1815
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001816void GrGpuGL::setTextureUnit(int unit) {
1817 GrAssert(unit >= 0 && unit < kNumStages);
1818 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001819 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001820 fActiveTextureUnitIdx = unit;
1821 }
1822}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001823
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001824void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001825 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1826 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001827 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1828 }
1829}
1830
reed@google.comac10a2d2010-12-22 21:39:39 +00001831/* On ES the internalFormat and format must match for TexImage and we use
1832 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1833 decide the internalFormat. However, on ES internalFormat for
1834 RenderBufferStorage* has to be a specific format (not a base format like
1835 GL_RGBA).
1836 */
twiz@google.com0f31ca72011-03-18 17:38:11 +00001837bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001838 switch (config) {
1839 case GrTexture::kRGBA_8888_PixelConfig:
1840 case GrTexture::kRGBX_8888_PixelConfig:
1841 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001842 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001843 return true;
1844 } else {
1845 return false;
1846 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001847 case GrTexture::kRGB_565_PixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001848 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1849 // with FBO extension desktop GL has
1850 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001851 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001852 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001853 case GrTexture::kRGBA_4444_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001854 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001855 return true;
1856 default:
1857 return false;
1858 }
1859}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001860
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001861void GrGpuGL::resetDirtyFlags() {
1862 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1863}
1864
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001865void GrGpuGL::setBuffers(bool indexed,
1866 int* extraVertexOffset,
1867 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001868
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001869 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001870
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001871 GrGLVertexBuffer* vbuf;
1872 switch (fGeometrySrc.fVertexSrc) {
1873 case kBuffer_GeometrySrcType:
1874 *extraVertexOffset = 0;
1875 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1876 break;
1877 case kArray_GeometrySrcType:
1878 case kReserved_GeometrySrcType:
1879 finalizeReservedVertices();
1880 *extraVertexOffset = fCurrPoolStartVertex;
1881 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1882 break;
1883 default:
1884 vbuf = NULL; // suppress warning
1885 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001886 }
1887
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001888 GrAssert(NULL != vbuf);
1889 GrAssert(!vbuf->isLocked());
1890 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001891 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001892 fHWGeometryState.fArrayPtrsDirty = true;
1893 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001894 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001895
1896 if (indexed) {
1897 GrAssert(NULL != extraIndexOffset);
1898
1899 GrGLIndexBuffer* ibuf;
1900 switch (fGeometrySrc.fIndexSrc) {
1901 case kBuffer_GeometrySrcType:
1902 *extraIndexOffset = 0;
1903 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1904 break;
1905 case kArray_GeometrySrcType:
1906 case kReserved_GeometrySrcType:
1907 finalizeReservedIndices();
1908 *extraIndexOffset = fCurrPoolStartIndex;
1909 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1910 break;
1911 default:
1912 ibuf = NULL; // suppress warning
1913 GrCrash("Unknown geometry src type!");
1914 }
1915
1916 GrAssert(NULL != ibuf);
1917 GrAssert(!ibuf->isLocked());
1918 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001919 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001920 fHWGeometryState.fIndexBuffer = ibuf;
1921 }
1922 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001923}