blob: 86d634219bacceeee60a285b60e6a3f4bfc92820 [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));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000484 fHWAAState.fMSAAEnabled = false;
485 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000486 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000487
twiz@google.com0f31ca72011-03-18 17:38:11 +0000488 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000489 fHWDrawState.fFlagBits = 0;
490
reed@google.comac10a2d2010-12-22 21:39:39 +0000491 // we only ever use lines in hairline mode
492 GR_GL(LineWidth(1));
493
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000494 // invalid
495 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000496
reed@google.comac10a2d2010-12-22 21:39:39 +0000497 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000498 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
499 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000500
501 fHWDrawState.fBlendConstant = 0x00000000;
502 GR_GL(BlendColor(0,0,0,0));
503
reed@google.comac10a2d2010-12-22 21:39:39 +0000504 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000505
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000506 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000507
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000508 for (int s = 0; s < kNumStages; ++s) {
509 fHWDrawState.fTextures[s] = NULL;
510 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
511 -GR_ScalarMax,
512 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000513
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000514 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000515 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000516
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000517 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000518 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000519 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000520 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000521
bsalomon@google.comd302f142011-03-03 13:54:13 +0000522 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000523 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000524 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000525
526 fHWGeometryState.fIndexBuffer = NULL;
527 fHWGeometryState.fVertexBuffer = NULL;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000528 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
529 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000530 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000531
twiz@google.com0f31ca72011-03-18 17:38:11 +0000532 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000533 fHWDrawState.fRenderTarget = NULL;
534}
535
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000536GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
reed@google.comac10a2d2010-12-22 21:39:39 +0000537 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000538 int stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000539 bool isMultisampled,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000540 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000541 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000542 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
543 rtIDs.fStencilRenderbufferID = 0;
544 rtIDs.fMSColorRenderbufferID = 0;
545 rtIDs.fTexFBOID = 0;
546 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000547 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000548
549 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000550 viewport.fLeft = 0;
551 viewport.fBottom = 0;
552 viewport.fWidth = width;
553 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000554
twiz@google.com0f31ca72011-03-18 17:38:11 +0000555 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
556 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000557
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000558 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
559 isMultisampled, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000560}
561
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000562GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000563
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000564 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000565
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000566 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000567 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
568 rtIDs.fMSColorRenderbufferID = 0;
569 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000570
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000571 GrGLIRect viewport;
572 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000573 GrGLuint stencilBits;
574 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000575
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000576 GrGLint samples;
577 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
578
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000579 rtIDs.fOwnIDs = false;
580
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000581 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
582 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000583}
584
bsalomon@google.com5782d712011-01-21 21:03:59 +0000585///////////////////////////////////////////////////////////////////////////////
586
twiz@google.com0f31ca72011-03-18 17:38:11 +0000587static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000588
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000589struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000590 GrGLenum fEnum;
591 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000592 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000593};
594
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000595const StencilFormat* GrGLStencilFormats() {
596 // defines stencil formats from more to less preferred
597 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000598 {GR_GL_STENCIL_INDEX8, 8, false},
599 {GR_GL_STENCIL_INDEX16, 16, false},
600 {GR_GL_DEPTH24_STENCIL8, 8, true },
601 {GR_GL_STENCIL_INDEX4, 4, false},
602 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
603 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
604 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000605 };
606
607 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000608 {GR_GL_STENCIL_INDEX8, 8, false},
609 {GR_GL_DEPTH24_STENCIL8, 8, true },
610 {GR_GL_STENCIL_INDEX4, 4, false},
611 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000612 };
613
614 if (GR_GL_SUPPORT_DESKTOP) {
615 return desktopStencilFormats;
616 } else {
617 return esStencilFormats;
618 }
619}
620
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000621// good to set a break-point here to know when createTexture fails
622static GrTexture* return_null_texture() {
623// GrAssert(!"null texture");
624 return NULL;
625}
626
627#if GR_DEBUG
628static size_t as_size_t(int x) {
629 return x;
630}
631#endif
632
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000633GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
634 const void* srcData,
635 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000636
637#if GR_COLLECT_STATS
638 ++fStats.fTextureCreateCnt;
639#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000640
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000641 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000642
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000643 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000644 GR_GL_NEAREST,
645 GR_GL_CLAMP_TO_EDGE,
646 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000647 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000648
reed@google.comac10a2d2010-12-22 21:39:39 +0000649 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000650 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000651
652 glDesc.fContentWidth = desc.fWidth;
653 glDesc.fContentHeight = desc.fHeight;
654 glDesc.fAllocWidth = desc.fWidth;
655 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000656 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000657 glDesc.fFormat = desc.fFormat;
658
659 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
660 if (!canBeTexture(desc.fFormat,
661 &internalFormat,
662 &glDesc.fUploadFormat,
663 &glDesc.fUploadType)) {
664 return return_null_texture();
665 }
666
667 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000668 GrGLint samples = fAASamples[desc.fAALevel];
reed@google.comac10a2d2010-12-22 21:39:39 +0000669 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
670 GrPrintf("AA RT requested but not supported on this platform.");
671 }
672
673 GR_GL(GenTextures(1, &glDesc.fTextureID));
674 if (!glDesc.fTextureID) {
675 return return_null_texture();
676 }
677
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000678 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000679
reed@google.com5e762232011-04-04 18:15:49 +0000680 // in case we need a temporary, trimmed copy of the src pixels
681 GrAutoSMalloc<128 * 128> trimStorage;
682
reed@google.comac10a2d2010-12-22 21:39:39 +0000683 /*
684 * check if our srcData has extra bytes past each row. If so, we need
685 * to trim those off here, since GL doesn't let us pass the rowBytes as
686 * a parameter to glTexImage2D
687 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000688 if (GR_GL_SUPPORT_DESKTOP) {
689 if (srcData) {
690 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
691 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000692 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000693 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000694 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
695 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000696 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000697 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000698 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000699 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000700 for (uint32_t y = 0; y < desc.fHeight; y++) {
701 memcpy(dst, src, trimRowBytes);
702 src += rowBytes;
703 dst += trimRowBytes;
704 }
705 // now point srcData to our trimmed version
706 srcData = trimStorage.get();
707 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000708 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000709
reed@google.comac10a2d2010-12-22 21:39:39 +0000710 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000711 if (!this->npotRenderTargetSupport()) {
712 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
713 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
714 }
715
reed@google.comac10a2d2010-12-22 21:39:39 +0000716 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
717 glDesc.fAllocWidth);
718 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
719 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000720 } else if (!this->npotTextureSupport()) {
721 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
722 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000723 }
724
twiz@google.com0f31ca72011-03-18 17:38:11 +0000725 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
726 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
727 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000728 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000729 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
730 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000731 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000732 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
733 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000734 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000735 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
736 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000737 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000738
twiz@google.com0f31ca72011-03-18 17:38:11 +0000739 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000740 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000741 supports8BitPalette()) {
742 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
743 GrAssert(desc.fWidth == glDesc.fAllocWidth);
744 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000745 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
746 kColorTableSize;
747 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000748 glDesc.fAllocWidth, glDesc.fAllocHeight,
749 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000750 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000751 } else {
752 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
753 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000754 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000755 glDesc.fAllocWidth, glDesc.fAllocHeight,
756 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000757 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000758 desc.fHeight, glDesc.fUploadFormat,
759 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000760 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000761
762 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
763 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
764 uint32_t maxTexels = extraW * extraH;
765 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
766 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
767
768 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
769
770 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
771 if (extraH) {
772 uint8_t* lastRowStart = (uint8_t*) srcData +
773 (desc.fHeight - 1) * rowSize;
774 uint8_t* extraRowStart = (uint8_t*)texels.get();
775
776 for (uint32_t i = 0; i < extraH; ++i) {
777 memcpy(extraRowStart, lastRowStart, rowSize);
778 extraRowStart += rowSize;
779 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000780 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000781 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
782 texels.get()));
783 }
784 if (extraW) {
785 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
786 uint8_t* extraTexel = (uint8_t*)texels.get();
787 for (uint32_t j = 0; j < desc.fHeight; ++j) {
788 for (uint32_t i = 0; i < extraW; ++i) {
789 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
790 extraTexel += glDesc.fUploadByteCount;
791 }
792 edgeTexel += rowSize;
793 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000794 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000795 desc.fHeight, glDesc.fUploadFormat,
796 glDesc.fUploadType, texels.get()));
797 }
798 if (extraW && extraH) {
799 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
800 - glDesc.fUploadByteCount;
801 uint8_t* extraTexel = (uint8_t*)texels.get();
802 for (uint32_t i = 0; i < extraW*extraH; ++i) {
803 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
804 extraTexel += glDesc.fUploadByteCount;
805 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000806 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000807 extraW, extraH, glDesc.fUploadFormat,
808 glDesc.fUploadType, texels.get()));
809 }
810
811 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000812 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000813 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
814 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000815 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000816 }
817 }
818
819 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
820
821 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
822 rtIDs.fStencilRenderbufferID = 0;
823 rtIDs.fMSColorRenderbufferID = 0;
824 rtIDs.fRTFBOID = 0;
825 rtIDs.fTexFBOID = 0;
826 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000827 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000828
829 if (renderTarget) {
830#if GR_COLLECT_STATS
831 ++fStats.fRenderTargetCreateCnt;
832#endif
833 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000834 GrGLenum status;
835 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000836
837 // If need have both RT flag and srcData we have
838 // to invert the data before uploading because FBO
839 // will be rendered bottom up
840 GrAssert(NULL == srcData);
841 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
842
twiz@google.com59a190b2011-03-14 21:23:01 +0000843 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000844 GrAssert(rtIDs.fTexFBOID);
845
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000846 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000847 // to one and then resolve to the texture bound to the other.
848 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000849 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000850 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000851 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000852 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
853 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000854 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000855 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000856 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
857 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000858 return return_null_texture();
859 }
860 } else {
861 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
862 }
bsalomon@google.comf6a7c112011-03-24 16:14:10 +0000863 if (!(kNoStencil_TextureFlag & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000864 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000865 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000866 }
867
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000868 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000869 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000870 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000871 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000872
twiz@google.com0f31ca72011-03-18 17:38:11 +0000873 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000874
875 const StencilFormat* stencilFormats = GrGLStencilFormats();
876 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000877 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000878 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000879 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000880 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000881 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000882 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000883 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000884 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000885 glDesc.fAllocWidth,
886 glDesc.fAllocHeight));
887 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000888 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000889 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000890 glDesc.fAllocWidth,
891 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000892 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000893 err = GrGLGetGLInterface()->fGetError();
894 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000895 continue;
896 }
897 }
898 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
899 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000900 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000901 rtIDs.fMSColorRenderbufferID));
902 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000903 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000904 samples,
905 msColorRenderbufferFormat,
906 glDesc.fAllocWidth,
907 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000908 err = GrGLGetGLInterface()->fGetError();
909 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000910 continue;
911 }
912 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000913 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000914
915#if GR_COLLECT_STATS
916 ++fStats.fRenderTargetChngCnt;
917#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000918 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
919 GR_GL_COLOR_ATTACHMENT0,
920 GR_GL_TEXTURE_2D,
921 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000923 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
924 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000925 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
926 status, desc.fWidth, desc.fHeight);
927 continue;
928 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000929 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000930 #if GR_COLLECT_STATS
931 ++fStats.fRenderTargetChngCnt;
932 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000933 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
934 GR_GL_COLOR_ATTACHMENT0,
935 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000936 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000937
938 }
939 if (rtIDs.fStencilRenderbufferID) {
940 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000941 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
942 GR_GL_STENCIL_ATTACHMENT,
943 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000944 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +0000945 // if it is a packed format bind to depth also, otherwise
946 // we may get an unsupported fbo completeness result
947 if (stencilFormats[i].fPacked) {
948 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
949 GR_GL_DEPTH_ATTACHMENT,
950 GR_GL_RENDERBUFFER,
951 rtIDs.fStencilRenderbufferID));
952 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000953 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000954 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000955
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000956 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000957 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
958 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +0000959 // undo the depth bind
960 if (rtIDs.fStencilRenderbufferID &&
961 stencilFormats[i].fPacked) {
962 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
963 GR_GL_DEPTH_ATTACHMENT,
964 GR_GL_RENDERBUFFER,
965 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000966 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000967 continue;
968 }
969 // we're successful!
970 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000971 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000972 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000973 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000974 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000975 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000976 }
977 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000978 break;
979 }
980 if (failed) {
981 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000982 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000983 }
984 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000985 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000986 }
987 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000988 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000989 }
990 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000991 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000992 }
993 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
994 return return_null_texture();
995 }
996 }
997#ifdef TRACE_TEXTURE_CREATION
998 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
999 tex->fTextureID, width, height, tex->fUploadByteCount);
1000#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001001 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001002
1003 if (0 != rtIDs.fTexFBOID) {
1004 GrRenderTarget* rt = tex->asRenderTarget();
1005 // We've messed with FBO state but may not have set the correct viewport
1006 // so just dirty the rendertarget state to force a resend.
1007 fHWDrawState.fRenderTarget = NULL;
1008
1009 // clear the new stencil buffer if we have one
bsalomon@google.comf6a7c112011-03-24 16:14:10 +00001010 if (!(desc.fFlags & kNoStencil_TextureFlag)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001011 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1012 fCurrDrawState.fRenderTarget = rt;
1013 eraseStencil(0, ~0);
1014 fCurrDrawState.fRenderTarget = rtSave;
1015 }
1016 }
1017 return tex;
1018}
1019
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001020GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001021 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001022 GR_GL(GenBuffers(1, &id));
1023 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001024 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001025 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001026 GrGLClearErr();
1027 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001028 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1029 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1030 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001031 GR_GL(DeleteBuffers(1, &id));
1032 // deleting bound buffer does implicit bind to 0
1033 fHWGeometryState.fVertexBuffer = NULL;
1034 return NULL;
1035 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001036 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001037 size, dynamic);
1038 fHWGeometryState.fVertexBuffer = vertexBuffer;
1039 return vertexBuffer;
1040 }
1041 return NULL;
1042}
1043
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001044GrIndexBuffer* GrGpuGL::createIndexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001045 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001046 GR_GL(GenBuffers(1, &id));
1047 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001048 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001049 GrGLClearErr();
1050 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001051 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1052 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1053 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001054 GR_GL(DeleteBuffers(1, &id));
1055 // deleting bound buffer does implicit bind to 0
1056 fHWGeometryState.fIndexBuffer = NULL;
1057 return NULL;
1058 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001059 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001060 size, dynamic);
1061 fHWGeometryState.fIndexBuffer = indexBuffer;
1062 return indexBuffer;
1063 }
1064 return NULL;
1065}
1066
reed@google.comac10a2d2010-12-22 21:39:39 +00001067void GrGpuGL::flushScissor(const GrIRect* rect) {
1068 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001069 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001070 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001071
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001072 GrGLIRect scissor;
1073 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001074 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001075 rect->width(), rect->height());
1076 if (scissor.contains(vp)) {
1077 rect = NULL;
1078 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001079 }
1080
1081 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001082 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001083 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001084 fHWBounds.fScissorRect = scissor;
1085 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001086 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001087 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 fHWBounds.fScissorEnabled = true;
1089 }
1090 } else {
1091 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001092 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001093 fHWBounds.fScissorEnabled = false;
1094 }
1095 }
1096}
1097
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001098void GrGpuGL::eraseColorHelper(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001099 if (NULL == fCurrDrawState.fRenderTarget) {
1100 return;
1101 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001102 flushRenderTarget();
1103 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001104 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001105 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001106 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001107 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001108 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001109 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1110 GrColorUnpackG(color)/255.f,
1111 GrColorUnpackB(color)/255.f,
1112 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001113 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001114}
1115
1116void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001117 if (NULL == fCurrDrawState.fRenderTarget) {
1118 return;
1119 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001120 flushRenderTarget();
1121 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001122 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001123 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001124 }
1125 GR_GL(StencilMask(mask));
1126 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001127 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001128 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001129}
1130
bsalomon@google.comd302f142011-03-03 13:54:13 +00001131void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001132 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001133#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001134 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001135 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001136 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001137#else
1138 // we could just clear the clip bit but when we go through
1139 // angle a partial stencil mask will cause clears to be
1140 // turned into draws. Our contract on GrDrawTarget says that
1141 // changing the clip between stencil passes may or may not
1142 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001143 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001144#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001145 flushRenderTarget();
1146 flushScissor(&rect);
1147 GR_GL(StencilMask(clipStencilMask));
1148 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001149 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001150 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001151}
1152
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001153void GrGpuGL::forceRenderTargetFlushHelper() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001154 flushRenderTarget();
1155}
1156
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001157bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height,
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001158 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001159 GrGLenum internalFormat; // we don't use this for glReadPixels
1160 GrGLenum format;
1161 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001162 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1163 return false;
1164 }
1165
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001166 if (NULL == fCurrDrawState.fRenderTarget) {
1167 return false;
1168 }
1169 flushRenderTarget();
1170
bsalomon@google.comd302f142011-03-03 13:54:13 +00001171 const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
1172
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001173 // the read rect is viewport-relative
1174 GrGLIRect readRect;
1175 readRect.setRelativeTo(glvp, left, top, width, height);
1176 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001177 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001178 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001179
1180 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1181 // API presents top-to-bottom
1182 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001183 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001184 GrAutoMalloc rowStorage(stride);
1185 void* tmp = rowStorage.get();
1186
1187 const int halfY = height >> 1;
1188 char* top = reinterpret_cast<char*>(buffer);
1189 char* bottom = top + (height - 1) * stride;
1190 for (int y = 0; y < halfY; y++) {
1191 memcpy(tmp, top, stride);
1192 memcpy(top, bottom, stride);
1193 memcpy(bottom, tmp, stride);
1194 top += stride;
1195 bottom -= stride;
1196 }
1197 }
1198 return true;
1199}
1200
1201void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001202
1203 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1204
reed@google.comac10a2d2010-12-22 21:39:39 +00001205 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1206 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001207 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001208 #if GR_COLLECT_STATS
1209 ++fStats.fRenderTargetChngCnt;
1210 #endif
1211 rt->setDirty(true);
1212 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001213 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1214 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001215 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1216 }
1217 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001218 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001219 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001220 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001221 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001222 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001223 fHWBounds.fViewportRect = vp;
1224 }
1225 }
1226}
1227
twiz@google.com0f31ca72011-03-18 17:38:11 +00001228GrGLenum gPrimitiveType2GLMode[] = {
1229 GR_GL_TRIANGLES,
1230 GR_GL_TRIANGLE_STRIP,
1231 GR_GL_TRIANGLE_FAN,
1232 GR_GL_POINTS,
1233 GR_GL_LINES,
1234 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001235};
1236
bsalomon@google.comd302f142011-03-03 13:54:13 +00001237#define SWAP_PER_DRAW 0
1238
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001239#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001240 #if GR_MAC_BUILD
1241 #include <AGL/agl.h>
1242 #elif GR_WIN32_BUILD
1243 void SwapBuf() {
1244 DWORD procID = GetCurrentProcessId();
1245 HWND hwnd = GetTopWindow(GetDesktopWindow());
1246 while(hwnd) {
1247 DWORD wndProcID = 0;
1248 GetWindowThreadProcessId(hwnd, &wndProcID);
1249 if(wndProcID == procID) {
1250 SwapBuffers(GetDC(hwnd));
1251 }
1252 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1253 }
1254 }
1255 #endif
1256#endif
1257
bsalomon@google.comffca4002011-02-22 20:34:01 +00001258void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001259 uint32_t startVertex,
1260 uint32_t startIndex,
1261 uint32_t vertexCount,
1262 uint32_t indexCount) {
1263 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1264
twiz@google.com0f31ca72011-03-18 17:38:11 +00001265 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001266
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001267 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1268 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1269
1270 // our setupGeometry better have adjusted this to zero since
1271 // DrawElements always draws from the begining of the arrays for idx 0.
1272 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001273
1274 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001275 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001276#if SWAP_PER_DRAW
1277 glFlush();
1278 #if GR_MAC_BUILD
1279 aglSwapBuffers(aglGetCurrentContext());
1280 int set_a_break_pt_here = 9;
1281 aglSwapBuffers(aglGetCurrentContext());
1282 #elif GR_WIN32_BUILD
1283 SwapBuf();
1284 int set_a_break_pt_here = 9;
1285 SwapBuf();
1286 #endif
1287#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001288}
1289
bsalomon@google.comffca4002011-02-22 20:34:01 +00001290void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001291 uint32_t startVertex,
1292 uint32_t vertexCount) {
1293 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1294
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001295 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1296
1297 // our setupGeometry better have adjusted this to zero.
1298 // DrawElements doesn't take an offset so we always adjus the startVertex.
1299 GrAssert(0 == startVertex);
1300
1301 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1302 // account for startVertex in the DrawElements case. So we always
1303 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001304 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001305#if SWAP_PER_DRAW
1306 glFlush();
1307 #if GR_MAC_BUILD
1308 aglSwapBuffers(aglGetCurrentContext());
1309 int set_a_break_pt_here = 9;
1310 aglSwapBuffers(aglGetCurrentContext());
1311 #elif GR_WIN32_BUILD
1312 SwapBuf();
1313 int set_a_break_pt_here = 9;
1314 SwapBuf();
1315 #endif
1316#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001317}
1318
reed@google.comac10a2d2010-12-22 21:39:39 +00001319void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1320 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1321
1322 if (NULL != rt && rt->needsResolve()) {
1323 GrAssert(kNone_MSFBO != fMSFBOType);
1324 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001325 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001326 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001327 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001328 rt->textureFBOID()));
1329 #if GR_COLLECT_STATS
1330 ++fStats.fRenderTargetChngCnt;
1331 #endif
1332 // make sure we go through set render target
1333 fHWDrawState.fRenderTarget = NULL;
1334
twiz@google.com0f31ca72011-03-18 17:38:11 +00001335 GrGLint left = 0;
1336 GrGLint right = texture->width();
reed@google.comac10a2d2010-12-22 21:39:39 +00001337 // we will have rendered to the top of the FBO.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001338 GrGLint top = texture->allocHeight();
1339 GrGLint bottom = texture->allocHeight() - texture->height();
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001340 if (kAppleES_MSFBO == fMSFBOType) {
1341 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001342 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001343 GR_GL(Scissor(left, bottom, right-left, top-bottom));
twiz@google.com59a190b2011-03-14 21:23:01 +00001344 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001345 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001346 fHWBounds.fScissorEnabled = true;
1347 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001348 if (kDesktopARB_MSFBO != fMSFBOType) {
1349 // these respect the scissor during the blit, so disable it.
1350 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1351 flushScissor(NULL);
1352 }
twiz@google.com59a190b2011-03-14 21:23:01 +00001353 GR_GL(BlitFramebuffer(left, bottom, right, top,
reed@google.comac10a2d2010-12-22 21:39:39 +00001354 left, bottom, right, top,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001355 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001356 }
1357 rt->setDirty(false);
reed@google.comac10a2d2010-12-22 21:39:39 +00001358 }
1359}
1360
twiz@google.com0f31ca72011-03-18 17:38:11 +00001361static const GrGLenum grToGLStencilFunc[] = {
1362 GR_GL_ALWAYS, // kAlways_StencilFunc
1363 GR_GL_NEVER, // kNever_StencilFunc
1364 GR_GL_GREATER, // kGreater_StencilFunc
1365 GR_GL_GEQUAL, // kGEqual_StencilFunc
1366 GR_GL_LESS, // kLess_StencilFunc
1367 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1368 GR_GL_EQUAL, // kEqual_StencilFunc,
1369 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001370};
1371GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1372GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1373GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1374GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1375GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1376GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1377GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1378GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1379GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1380
twiz@google.com0f31ca72011-03-18 17:38:11 +00001381static const GrGLenum grToGLStencilOp[] = {
1382 GR_GL_KEEP, // kKeep_StencilOp
1383 GR_GL_REPLACE, // kReplace_StencilOp
1384 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1385 GR_GL_INCR, // kIncClamp_StencilOp
1386 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1387 GR_GL_DECR, // kDecClamp_StencilOp
1388 GR_GL_ZERO, // kZero_StencilOp
1389 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001390};
1391GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1392GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1393GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1394GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1395GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1396GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1397GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1398GR_STATIC_ASSERT(6 == kZero_StencilOp);
1399GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1400
reed@google.comac10a2d2010-12-22 21:39:39 +00001401void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001402 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001403
1404 // use stencil for clipping if clipping is enabled and the clip
1405 // has been written into the stencil.
1406 bool stencilClip = fClipState.fClipInStencil &&
1407 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001408 bool stencilChange = fHWStencilClip != stencilClip ||
1409 fHWDrawState.fStencilSettings != *settings ||
1410 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1411 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001412
1413 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001414
bsalomon@google.comd302f142011-03-03 13:54:13 +00001415 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1416 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001417
bsalomon@google.comd302f142011-03-03 13:54:13 +00001418 if (settings->isDisabled()) {
1419 if (stencilClip) {
1420 settings = &gClipStencilSettings;
1421 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001422 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001423
1424 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001425 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001426 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001427 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001428 #if GR_DEBUG
1429 if (!fStencilWrapOpsSupport) {
1430 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1431 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1432 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1433 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1434 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1435 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1436 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1437 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1438 }
1439 #endif
1440 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1441 GrAssert(stencilBits ||
1442 (GrStencilSettings::gDisabled ==
1443 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001444 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1445 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001446
1447 unsigned int frontRef = settings->fFrontFuncRef;
1448 unsigned int frontMask = settings->fFrontFuncMask;
1449 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001450 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001451
1452 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1453
1454 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1455 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1456 } else {
1457 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1458
1459 ConvertStencilFuncAndMask(settings->fFrontFunc,
1460 stencilClip,
1461 clipStencilMask,
1462 userStencilMask,
1463 &frontRef,
1464 &frontMask);
1465 frontWriteMask &= userStencilMask;
1466 }
1467 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001468 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001469 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001470 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001471 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001472 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001473 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001474 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001475 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001476 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001477
1478 unsigned int backRef = settings->fBackFuncRef;
1479 unsigned int backMask = settings->fBackFuncMask;
1480 unsigned int backWriteMask = settings->fBackWriteMask;
1481
1482
1483 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1484 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1485 backFunc = grToGLStencilFunc[settings->fBackFunc];
1486 } else {
1487 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1488 ConvertStencilFuncAndMask(settings->fBackFunc,
1489 stencilClip,
1490 clipStencilMask,
1491 userStencilMask,
1492 &backRef,
1493 &backMask);
1494 backWriteMask &= userStencilMask;
1495 }
1496
twiz@google.com0f31ca72011-03-18 17:38:11 +00001497 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1498 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1499 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1500 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1501 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001502 grToGLStencilOp[settings->fFrontPassOp],
1503 grToGLStencilOp[settings->fFrontPassOp]));
1504
twiz@google.com0f31ca72011-03-18 17:38:11 +00001505 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001506 grToGLStencilOp[settings->fBackPassOp],
1507 grToGLStencilOp[settings->fBackPassOp]));
1508 } else {
1509 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1510 GR_GL(StencilMask(frontWriteMask));
1511 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1512 grToGLStencilOp[settings->fFrontPassOp],
1513 grToGLStencilOp[settings->fFrontPassOp]));
1514 }
1515 }
1516 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001517 fHWStencilClip = stencilClip;
1518 }
1519}
1520
bsalomon@google.com0650e812011-04-08 18:07:53 +00001521bool GrGpuGL::useSmoothLines() {
1522 // there is a conflict between using smooth lines and our use of
1523 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1524 // but not in a premul-alpha way. So we only use them when our alpha
1525 // is 0xff.
1526
1527 // TODO: write a smarter line frag shader.
1528
1529 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1530 canDisableBlend();
1531}
1532
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001533void GrGpuGL::flushAAState(GrPrimitiveType type) {
1534 if (GR_GL_SUPPORT_DESKTOP) {
1535 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1536 // smooth lines.
1537
1538 // we prefer smooth lines over multisampled lines
1539 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001540 if (GrIsPrimTypeLines(type)) {
1541 bool smooth = useSmoothLines();
1542 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001543 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1544 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001545 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001546 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1547 fHWAAState.fSmoothLineEnabled = false;
1548 }
1549 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1550 fHWAAState.fMSAAEnabled) {
1551 GR_GL(Disable(GR_GL_MULTISAMPLE));
1552 fHWAAState.fMSAAEnabled = false;
1553 }
1554 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1555 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1556 fHWAAState.fMSAAEnabled) {
1557 if (fHWAAState.fMSAAEnabled) {
1558 GR_GL(Disable(GR_GL_MULTISAMPLE));
1559 fHWAAState.fMSAAEnabled = false;
1560 } else {
1561 GR_GL(Enable(GR_GL_MULTISAMPLE));
1562 fHWAAState.fMSAAEnabled = true;
1563 }
1564 }
1565 }
1566}
1567
bsalomon@google.com0650e812011-04-08 18:07:53 +00001568void GrGpuGL::flushBlend(GrPrimitiveType type) {
1569 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1570 if (fHWBlendDisabled) {
1571 GR_GL(Enable(GR_GL_BLEND));
1572 fHWBlendDisabled = false;
1573 }
1574 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1575 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1576 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1577 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1578 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1579 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1580 }
1581 } else {
1582 bool blendOff = canDisableBlend();
1583 if (fHWBlendDisabled != blendOff) {
1584 if (blendOff) {
1585 GR_GL(Disable(GR_GL_BLEND));
1586 } else {
1587 GR_GL(Enable(GR_GL_BLEND));
1588 }
1589 fHWBlendDisabled = blendOff;
1590 }
1591 if (!blendOff) {
1592 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1593 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1594 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1595 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1596 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1597 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1598 }
1599 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1600 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1601 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1602
1603 float c[] = {
1604 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1605 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1606 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1607 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1608 };
1609 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1610 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1611 }
1612 }
1613 }
1614}
1615
bsalomon@google.comffca4002011-02-22 20:34:01 +00001616bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001617
1618 // GrGpu::setupClipAndFlushState should have already checked this
1619 // and bailed if not true.
1620 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001621
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001622 for (int s = 0; s < kNumStages; ++s) {
1623 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001624
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001625 // bind texture and set sampler state
1626 if (usingTexture) {
1627 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001628
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001629 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001630 // if we created a rt/tex and rendered to it without using a
1631 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001632 // the last bound texture, but it needs resolving. So keep this
1633 // out of the "last != next" check.
1634 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001635
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001636 if (fHWDrawState.fTextures[s] != nextTexture) {
1637 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001638 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001639 #if GR_COLLECT_STATS
1640 ++fStats.fTextureChngCnt;
1641 #endif
1642 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1643 fHWDrawState.fTextures[s] = nextTexture;
1644 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001645
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001646 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001647 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001648 nextTexture->getTexParams();
1649 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001650
twiz@google.com0f31ca72011-03-18 17:38:11 +00001651 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1652 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001653 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001654 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001655 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001656 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001657
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001658 if (newTexParams.fFilter != oldTexParams.fFilter) {
1659 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001660 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1661 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001662 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001663 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1664 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001665 newTexParams.fFilter));
1666 }
1667 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1668 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001669 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1670 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001671 newTexParams.fWrapS));
1672 }
1673 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1674 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001675 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1676 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001677 newTexParams.fWrapT));
1678 }
1679 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001680
1681 // The texture matrix has to compensate for texture width/height
1682 // and NPOT-embedded-in-POT
1683 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001684 } else {
1685 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001686 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001687 }
1688 }
1689 }
1690
1691 flushRenderTarget();
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001692 flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001693 flushBlend(type);
1694
reed@google.comac10a2d2010-12-22 21:39:39 +00001695 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1696 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1697 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001698 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001699 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001700 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001701 }
1702 }
1703
bsalomon@google.comd302f142011-03-03 13:54:13 +00001704 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1705 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001706 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001707 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001708 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001709 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001710 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001711 }
1712 GR_GL(ColorMask(mask, mask, mask, mask));
1713 }
1714
bsalomon@google.comd302f142011-03-03 13:54:13 +00001715 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1716 switch (fCurrDrawState.fDrawFace) {
1717 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001718 GR_GL(Enable(GR_GL_CULL_FACE));
1719 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001720 break;
1721 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001722 GR_GL(Enable(GR_GL_CULL_FACE));
1723 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001724 break;
1725 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001726 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001727 break;
1728 default:
1729 GrCrash("Unknown draw face.");
1730 }
1731 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1732 }
1733
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001734#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001735 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001736 for (int s = 0; s < kNumStages; ++s) {
1737 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1738 NULL == fCurrDrawState.fRenderTarget ||
1739 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001740 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001741 fCurrDrawState.fRenderTarget);
1742 }
1743#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001744
reed@google.comac10a2d2010-12-22 21:39:39 +00001745 flushStencil();
1746
bsalomon@google.comd302f142011-03-03 13:54:13 +00001747 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001748 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001749 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001750}
1751
1752void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001753 if (fHWGeometryState.fVertexBuffer != buffer) {
1754 fHWGeometryState.fArrayPtrsDirty = true;
1755 fHWGeometryState.fVertexBuffer = buffer;
1756 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001757}
1758
1759void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001760 if (fHWGeometryState.fVertexBuffer == buffer) {
1761 // deleting bound buffer does implied bind to 0
1762 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001763 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001764 }
1765}
1766
1767void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1768 fGeometrySrc.fIndexBuffer = buffer;
1769}
1770
1771void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001772 if (fHWGeometryState.fIndexBuffer == buffer) {
1773 // deleting bound buffer does implied bind to 0
1774 fHWGeometryState.fIndexBuffer = NULL;
1775 }
1776}
1777
reed@google.comac10a2d2010-12-22 21:39:39 +00001778void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1779 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001780 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001781 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001782 }
1783 if (fHWDrawState.fRenderTarget == renderTarget) {
1784 fHWDrawState.fRenderTarget = NULL;
1785 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001786}
1787
1788void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001789 for (int s = 0; s < kNumStages; ++s) {
1790 if (fCurrDrawState.fTextures[s] == texture) {
1791 fCurrDrawState.fTextures[s] = NULL;
1792 }
1793 if (fHWDrawState.fTextures[s] == texture) {
1794 // deleting bound texture does implied bind to 0
1795 fHWDrawState.fTextures[s] = NULL;
1796 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001797 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001798}
1799
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001800bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001801 GrGLenum* internalFormat,
1802 GrGLenum* format,
1803 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001804 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001805 case kRGBA_8888_GrPixelConfig:
1806 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001807 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001808 if (GR_GL_SUPPORT_ES) {
1809 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1810 // format for a BGRA is BGRA not RGBA (as on desktop)
1811 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1812 } else {
1813 *internalFormat = GR_GL_RGBA;
1814 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001815 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001816 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001817 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001818 *format = GR_GL_RGB;
1819 *internalFormat = GR_GL_RGB;
1820 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001821 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001822 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001823 *format = GR_GL_RGBA;
1824 *internalFormat = GR_GL_RGBA;
1825 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001826 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001827 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001828 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001829 *format = GR_GL_PALETTE8_RGBA8;
1830 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001831 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001832 } else {
1833 return false;
1834 }
1835 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001836 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001837 *format = GR_GL_ALPHA;
1838 *internalFormat = GR_GL_ALPHA;
1839 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001840 break;
1841 default:
1842 return false;
1843 }
1844 return true;
1845}
1846
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001847void GrGpuGL::setTextureUnit(int unit) {
1848 GrAssert(unit >= 0 && unit < kNumStages);
1849 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001850 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001851 fActiveTextureUnitIdx = unit;
1852 }
1853}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001854
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001855void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001856 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1857 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001858 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1859 }
1860}
1861
reed@google.comac10a2d2010-12-22 21:39:39 +00001862/* On ES the internalFormat and format must match for TexImage and we use
1863 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1864 decide the internalFormat. However, on ES internalFormat for
1865 RenderBufferStorage* has to be a specific format (not a base format like
1866 GL_RGBA).
1867 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001868bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001869 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001870 case kRGBA_8888_GrPixelConfig:
1871 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001872 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001873 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001874 return true;
1875 } else {
1876 return false;
1877 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001878 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001879 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1880 // with FBO extension desktop GL has
1881 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001882 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001883 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001884 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001885 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001886 return true;
1887 default:
1888 return false;
1889 }
1890}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001891
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001892void GrGpuGL::resetDirtyFlags() {
1893 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1894}
1895
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001896void GrGpuGL::setBuffers(bool indexed,
1897 int* extraVertexOffset,
1898 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001899
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001900 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001901
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001902 GrGLVertexBuffer* vbuf;
1903 switch (fGeometrySrc.fVertexSrc) {
1904 case kBuffer_GeometrySrcType:
1905 *extraVertexOffset = 0;
1906 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1907 break;
1908 case kArray_GeometrySrcType:
1909 case kReserved_GeometrySrcType:
1910 finalizeReservedVertices();
1911 *extraVertexOffset = fCurrPoolStartVertex;
1912 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1913 break;
1914 default:
1915 vbuf = NULL; // suppress warning
1916 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001917 }
1918
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001919 GrAssert(NULL != vbuf);
1920 GrAssert(!vbuf->isLocked());
1921 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001922 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001923 fHWGeometryState.fArrayPtrsDirty = true;
1924 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001925 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001926
1927 if (indexed) {
1928 GrAssert(NULL != extraIndexOffset);
1929
1930 GrGLIndexBuffer* ibuf;
1931 switch (fGeometrySrc.fIndexSrc) {
1932 case kBuffer_GeometrySrcType:
1933 *extraIndexOffset = 0;
1934 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1935 break;
1936 case kArray_GeometrySrcType:
1937 case kReserved_GeometrySrcType:
1938 finalizeReservedIndices();
1939 *extraIndexOffset = fCurrPoolStartIndex;
1940 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1941 break;
1942 default:
1943 ibuf = NULL; // suppress warning
1944 GrCrash("Unknown geometry src type!");
1945 }
1946
1947 GrAssert(NULL != ibuf);
1948 GrAssert(!ibuf->isLocked());
1949 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001950 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001951 fHWGeometryState.fIndexBuffer = ibuf;
1952 }
1953 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001954}