blob: a9e0e1d1873c73a1e0251504c7333bc99b815010 [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.com3f3ffd62011-01-18 17:14:52 +0000592};
593
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000594const StencilFormat* GrGLStencilFormats() {
595 // defines stencil formats from more to less preferred
596 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000597 {GR_GL_STENCIL_INDEX8, 8},
598 {GR_GL_STENCIL_INDEX16, 16},
599 {GR_GL_DEPTH24_STENCIL8, 8},
600 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000601 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS},
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000602 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000603 {0, 0}
604 };
605
606 static const StencilFormat esStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000607 {GR_GL_STENCIL_INDEX8, 8},
608 {GR_GL_DEPTH24_STENCIL8, 8},
609 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000610 {0, 0}
611 };
612
613 if (GR_GL_SUPPORT_DESKTOP) {
614 return desktopStencilFormats;
615 } else {
616 return esStencilFormats;
617 }
618}
619
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000620// good to set a break-point here to know when createTexture fails
621static GrTexture* return_null_texture() {
622// GrAssert(!"null texture");
623 return NULL;
624}
625
626#if GR_DEBUG
627static size_t as_size_t(int x) {
628 return x;
629}
630#endif
631
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000632GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
633 const void* srcData,
634 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000635
636#if GR_COLLECT_STATS
637 ++fStats.fTextureCreateCnt;
638#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000639
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000640 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000641
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000642 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000643 GR_GL_NEAREST,
644 GR_GL_CLAMP_TO_EDGE,
645 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000646 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000647
reed@google.comac10a2d2010-12-22 21:39:39 +0000648 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000649 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000650
651 glDesc.fContentWidth = desc.fWidth;
652 glDesc.fContentHeight = desc.fHeight;
653 glDesc.fAllocWidth = desc.fWidth;
654 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000655 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000656 glDesc.fFormat = desc.fFormat;
657
658 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
659 if (!canBeTexture(desc.fFormat,
660 &internalFormat,
661 &glDesc.fUploadFormat,
662 &glDesc.fUploadType)) {
663 return return_null_texture();
664 }
665
666 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000667 GrGLint samples = fAASamples[desc.fAALevel];
reed@google.comac10a2d2010-12-22 21:39:39 +0000668 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
669 GrPrintf("AA RT requested but not supported on this platform.");
670 }
671
672 GR_GL(GenTextures(1, &glDesc.fTextureID));
673 if (!glDesc.fTextureID) {
674 return return_null_texture();
675 }
676
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000677 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000678
reed@google.com5e762232011-04-04 18:15:49 +0000679 // in case we need a temporary, trimmed copy of the src pixels
680 GrAutoSMalloc<128 * 128> trimStorage;
681
reed@google.comac10a2d2010-12-22 21:39:39 +0000682 /*
683 * check if our srcData has extra bytes past each row. If so, we need
684 * to trim those off here, since GL doesn't let us pass the rowBytes as
685 * a parameter to glTexImage2D
686 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000687 if (GR_GL_SUPPORT_DESKTOP) {
688 if (srcData) {
689 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
690 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000691 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000692 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000693 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
694 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000695 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000696 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000697 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000698 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000699 for (uint32_t y = 0; y < desc.fHeight; y++) {
700 memcpy(dst, src, trimRowBytes);
701 src += rowBytes;
702 dst += trimRowBytes;
703 }
704 // now point srcData to our trimmed version
705 srcData = trimStorage.get();
706 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000707 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000708
reed@google.comac10a2d2010-12-22 21:39:39 +0000709 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000710 if (!this->npotRenderTargetSupport()) {
711 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
712 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
713 }
714
reed@google.comac10a2d2010-12-22 21:39:39 +0000715 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
716 glDesc.fAllocWidth);
717 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
718 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000719 } else if (!this->npotTextureSupport()) {
720 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
721 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000722 }
723
twiz@google.com0f31ca72011-03-18 17:38:11 +0000724 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
725 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
726 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000727 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000728 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
729 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000730 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000731 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
732 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000733 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000734 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
735 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000736 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000737
twiz@google.com0f31ca72011-03-18 17:38:11 +0000738 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000739 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000740 supports8BitPalette()) {
741 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
742 GrAssert(desc.fWidth == glDesc.fAllocWidth);
743 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000744 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
745 kColorTableSize;
746 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000747 glDesc.fAllocWidth, glDesc.fAllocHeight,
748 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000749 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000750 } else {
751 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
752 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000753 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000754 glDesc.fAllocWidth, glDesc.fAllocHeight,
755 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000756 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000757 desc.fHeight, glDesc.fUploadFormat,
758 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000759 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000760
761 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
762 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
763 uint32_t maxTexels = extraW * extraH;
764 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
765 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
766
767 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
768
769 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
770 if (extraH) {
771 uint8_t* lastRowStart = (uint8_t*) srcData +
772 (desc.fHeight - 1) * rowSize;
773 uint8_t* extraRowStart = (uint8_t*)texels.get();
774
775 for (uint32_t i = 0; i < extraH; ++i) {
776 memcpy(extraRowStart, lastRowStart, rowSize);
777 extraRowStart += rowSize;
778 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000779 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000780 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
781 texels.get()));
782 }
783 if (extraW) {
784 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
785 uint8_t* extraTexel = (uint8_t*)texels.get();
786 for (uint32_t j = 0; j < desc.fHeight; ++j) {
787 for (uint32_t i = 0; i < extraW; ++i) {
788 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
789 extraTexel += glDesc.fUploadByteCount;
790 }
791 edgeTexel += rowSize;
792 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000793 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000794 desc.fHeight, glDesc.fUploadFormat,
795 glDesc.fUploadType, texels.get()));
796 }
797 if (extraW && extraH) {
798 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
799 - glDesc.fUploadByteCount;
800 uint8_t* extraTexel = (uint8_t*)texels.get();
801 for (uint32_t i = 0; i < extraW*extraH; ++i) {
802 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
803 extraTexel += glDesc.fUploadByteCount;
804 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000805 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000806 extraW, extraH, glDesc.fUploadFormat,
807 glDesc.fUploadType, texels.get()));
808 }
809
810 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000811 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000812 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
813 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000814 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000815 }
816 }
817
818 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
819
820 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
821 rtIDs.fStencilRenderbufferID = 0;
822 rtIDs.fMSColorRenderbufferID = 0;
823 rtIDs.fRTFBOID = 0;
824 rtIDs.fTexFBOID = 0;
825 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000826 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000827
828 if (renderTarget) {
829#if GR_COLLECT_STATS
830 ++fStats.fRenderTargetCreateCnt;
831#endif
832 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000833 GrGLenum status;
834 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000835
836 // If need have both RT flag and srcData we have
837 // to invert the data before uploading because FBO
838 // will be rendered bottom up
839 GrAssert(NULL == srcData);
840 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
841
twiz@google.com59a190b2011-03-14 21:23:01 +0000842 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000843 GrAssert(rtIDs.fTexFBOID);
844
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000845 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000846 // to one and then resolve to the texture bound to the other.
847 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000848 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000849 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000850 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000851 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
852 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000853 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000854 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000855 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
856 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000857 return return_null_texture();
858 }
859 } else {
860 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
861 }
bsalomon@google.comf6a7c112011-03-24 16:14:10 +0000862 if (!(kNoStencil_TextureFlag & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000863 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000864 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000865 }
866
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000867 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000868 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000869 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000870 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000871
twiz@google.com0f31ca72011-03-18 17:38:11 +0000872 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000873
874 const StencilFormat* stencilFormats = GrGLStencilFormats();
875 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000876 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000877 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000878 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000879 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000880 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000881 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000882 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000883 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000884 glDesc.fAllocWidth,
885 glDesc.fAllocHeight));
886 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000887 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000888 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000889 glDesc.fAllocWidth,
890 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000891 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000892 err = GrGLGetGLInterface()->fGetError();
893 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000894 continue;
895 }
896 }
897 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
898 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000899 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000900 rtIDs.fMSColorRenderbufferID));
901 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000902 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000903 samples,
904 msColorRenderbufferFormat,
905 glDesc.fAllocWidth,
906 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000907 err = GrGLGetGLInterface()->fGetError();
908 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000909 continue;
910 }
911 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000912 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000913
914#if GR_COLLECT_STATS
915 ++fStats.fRenderTargetChngCnt;
916#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000917 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
918 GR_GL_COLOR_ATTACHMENT0,
919 GR_GL_TEXTURE_2D,
920 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000921 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000922 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
923 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000924 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
925 status, desc.fWidth, desc.fHeight);
926 continue;
927 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000928 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000929 #if GR_COLLECT_STATS
930 ++fStats.fRenderTargetChngCnt;
931 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000932 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
933 GR_GL_COLOR_ATTACHMENT0,
934 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000935 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000936
937 }
938 if (rtIDs.fStencilRenderbufferID) {
939 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000940 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
941 GR_GL_STENCIL_ATTACHMENT,
942 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000943 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000944 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000945 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000946
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000947 if (GR_GL_SUPPORT_DESKTOP) {
948 // On some implementations you have to be bound as DEPTH_STENCIL.
949 // (Even binding to DEPTH and STENCIL separately with the same
950 // buffer doesn't work.)
951 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000952 status != GR_GL_FRAMEBUFFER_COMPLETE) {
953 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
954 GR_GL_STENCIL_ATTACHMENT,
955 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000956 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000957 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
958 GR_GL_DEPTH_STENCIL_ATTACHMENT,
959 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000960 rtIDs.fStencilRenderbufferID));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000961 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000962 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000963 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000964 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000965 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
966 status, desc.fWidth, desc.fHeight);
967 if (GR_GL_SUPPORT_DESKTOP) {
968 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000969 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
970 GR_GL_DEPTH_STENCIL_ATTACHMENT,
971 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000972 0));
973 }
974 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000975 continue;
976 }
977 // we're successful!
978 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000979 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000980 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000981 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000982 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000983 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000984 }
985 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000986 break;
987 }
988 if (failed) {
989 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000990 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000991 }
992 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000993 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000994 }
995 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000996 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000997 }
998 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000999 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001000 }
1001 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1002 return return_null_texture();
1003 }
1004 }
1005#ifdef TRACE_TEXTURE_CREATION
1006 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1007 tex->fTextureID, width, height, tex->fUploadByteCount);
1008#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001009 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001010
1011 if (0 != rtIDs.fTexFBOID) {
1012 GrRenderTarget* rt = tex->asRenderTarget();
1013 // We've messed with FBO state but may not have set the correct viewport
1014 // so just dirty the rendertarget state to force a resend.
1015 fHWDrawState.fRenderTarget = NULL;
1016
1017 // clear the new stencil buffer if we have one
bsalomon@google.comf6a7c112011-03-24 16:14:10 +00001018 if (!(desc.fFlags & kNoStencil_TextureFlag)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001019 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1020 fCurrDrawState.fRenderTarget = rt;
1021 eraseStencil(0, ~0);
1022 fCurrDrawState.fRenderTarget = rtSave;
1023 }
1024 }
1025 return tex;
1026}
1027
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001028GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001029 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001030 GR_GL(GenBuffers(1, &id));
1031 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001032 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001033 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001034 GrGLClearErr();
1035 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001036 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1037 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1038 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001039 GR_GL(DeleteBuffers(1, &id));
1040 // deleting bound buffer does implicit bind to 0
1041 fHWGeometryState.fVertexBuffer = NULL;
1042 return NULL;
1043 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001044 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001045 size, dynamic);
1046 fHWGeometryState.fVertexBuffer = vertexBuffer;
1047 return vertexBuffer;
1048 }
1049 return NULL;
1050}
1051
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001052GrIndexBuffer* GrGpuGL::createIndexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001053 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001054 GR_GL(GenBuffers(1, &id));
1055 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001056 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001057 GrGLClearErr();
1058 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001059 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1060 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1061 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001062 GR_GL(DeleteBuffers(1, &id));
1063 // deleting bound buffer does implicit bind to 0
1064 fHWGeometryState.fIndexBuffer = NULL;
1065 return NULL;
1066 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001067 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001068 size, dynamic);
1069 fHWGeometryState.fIndexBuffer = indexBuffer;
1070 return indexBuffer;
1071 }
1072 return NULL;
1073}
1074
reed@google.comac10a2d2010-12-22 21:39:39 +00001075void GrGpuGL::flushScissor(const GrIRect* rect) {
1076 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001077 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001078 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001079
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001080 GrGLIRect scissor;
1081 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001082 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001083 rect->width(), rect->height());
1084 if (scissor.contains(vp)) {
1085 rect = NULL;
1086 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001087 }
1088
1089 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001090 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001091 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001092 fHWBounds.fScissorRect = scissor;
1093 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001095 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001096 fHWBounds.fScissorEnabled = true;
1097 }
1098 } else {
1099 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001100 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001101 fHWBounds.fScissorEnabled = false;
1102 }
1103 }
1104}
1105
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001106void GrGpuGL::eraseColorHelper(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001107 if (NULL == fCurrDrawState.fRenderTarget) {
1108 return;
1109 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001110 flushRenderTarget();
1111 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001112 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001113 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001114 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001115 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001116 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001117 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1118 GrColorUnpackG(color)/255.f,
1119 GrColorUnpackB(color)/255.f,
1120 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001121 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001122}
1123
1124void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001125 if (NULL == fCurrDrawState.fRenderTarget) {
1126 return;
1127 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001128 flushRenderTarget();
1129 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001130 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001131 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001132 }
1133 GR_GL(StencilMask(mask));
1134 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001135 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001136 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001137}
1138
bsalomon@google.comd302f142011-03-03 13:54:13 +00001139void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001140 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001141#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001142 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001143 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001144 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001145#else
1146 // we could just clear the clip bit but when we go through
1147 // angle a partial stencil mask will cause clears to be
1148 // turned into draws. Our contract on GrDrawTarget says that
1149 // changing the clip between stencil passes may or may not
1150 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001151 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001152#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001153 flushRenderTarget();
1154 flushScissor(&rect);
1155 GR_GL(StencilMask(clipStencilMask));
1156 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001157 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001158 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001159}
1160
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001161void GrGpuGL::forceRenderTargetFlushHelper() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001162 flushRenderTarget();
1163}
1164
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001165bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height,
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001166 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001167 GrGLenum internalFormat; // we don't use this for glReadPixels
1168 GrGLenum format;
1169 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001170 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1171 return false;
1172 }
1173
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001174 if (NULL == fCurrDrawState.fRenderTarget) {
1175 return false;
1176 }
1177 flushRenderTarget();
1178
bsalomon@google.comd302f142011-03-03 13:54:13 +00001179 const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
1180
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001181 // the read rect is viewport-relative
1182 GrGLIRect readRect;
1183 readRect.setRelativeTo(glvp, left, top, width, height);
1184 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001185 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001186 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001187
1188 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1189 // API presents top-to-bottom
1190 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001191 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001192 GrAutoMalloc rowStorage(stride);
1193 void* tmp = rowStorage.get();
1194
1195 const int halfY = height >> 1;
1196 char* top = reinterpret_cast<char*>(buffer);
1197 char* bottom = top + (height - 1) * stride;
1198 for (int y = 0; y < halfY; y++) {
1199 memcpy(tmp, top, stride);
1200 memcpy(top, bottom, stride);
1201 memcpy(bottom, tmp, stride);
1202 top += stride;
1203 bottom -= stride;
1204 }
1205 }
1206 return true;
1207}
1208
1209void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001210
1211 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1212
reed@google.comac10a2d2010-12-22 21:39:39 +00001213 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1214 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001215 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001216 #if GR_COLLECT_STATS
1217 ++fStats.fRenderTargetChngCnt;
1218 #endif
1219 rt->setDirty(true);
1220 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001221 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1222 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001223 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1224 }
1225 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001226 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001227 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001228 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001229 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001230 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001231 fHWBounds.fViewportRect = vp;
1232 }
1233 }
1234}
1235
twiz@google.com0f31ca72011-03-18 17:38:11 +00001236GrGLenum gPrimitiveType2GLMode[] = {
1237 GR_GL_TRIANGLES,
1238 GR_GL_TRIANGLE_STRIP,
1239 GR_GL_TRIANGLE_FAN,
1240 GR_GL_POINTS,
1241 GR_GL_LINES,
1242 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001243};
1244
bsalomon@google.comd302f142011-03-03 13:54:13 +00001245#define SWAP_PER_DRAW 0
1246
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001247#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001248 #if GR_MAC_BUILD
1249 #include <AGL/agl.h>
1250 #elif GR_WIN32_BUILD
1251 void SwapBuf() {
1252 DWORD procID = GetCurrentProcessId();
1253 HWND hwnd = GetTopWindow(GetDesktopWindow());
1254 while(hwnd) {
1255 DWORD wndProcID = 0;
1256 GetWindowThreadProcessId(hwnd, &wndProcID);
1257 if(wndProcID == procID) {
1258 SwapBuffers(GetDC(hwnd));
1259 }
1260 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1261 }
1262 }
1263 #endif
1264#endif
1265
bsalomon@google.comffca4002011-02-22 20:34:01 +00001266void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001267 uint32_t startVertex,
1268 uint32_t startIndex,
1269 uint32_t vertexCount,
1270 uint32_t indexCount) {
1271 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1272
twiz@google.com0f31ca72011-03-18 17:38:11 +00001273 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001274
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001275 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1276 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1277
1278 // our setupGeometry better have adjusted this to zero since
1279 // DrawElements always draws from the begining of the arrays for idx 0.
1280 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001281
1282 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001283 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001284#if SWAP_PER_DRAW
1285 glFlush();
1286 #if GR_MAC_BUILD
1287 aglSwapBuffers(aglGetCurrentContext());
1288 int set_a_break_pt_here = 9;
1289 aglSwapBuffers(aglGetCurrentContext());
1290 #elif GR_WIN32_BUILD
1291 SwapBuf();
1292 int set_a_break_pt_here = 9;
1293 SwapBuf();
1294 #endif
1295#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001296}
1297
bsalomon@google.comffca4002011-02-22 20:34:01 +00001298void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001299 uint32_t startVertex,
1300 uint32_t vertexCount) {
1301 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1302
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001303 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1304
1305 // our setupGeometry better have adjusted this to zero.
1306 // DrawElements doesn't take an offset so we always adjus the startVertex.
1307 GrAssert(0 == startVertex);
1308
1309 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1310 // account for startVertex in the DrawElements case. So we always
1311 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001312 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001313#if SWAP_PER_DRAW
1314 glFlush();
1315 #if GR_MAC_BUILD
1316 aglSwapBuffers(aglGetCurrentContext());
1317 int set_a_break_pt_here = 9;
1318 aglSwapBuffers(aglGetCurrentContext());
1319 #elif GR_WIN32_BUILD
1320 SwapBuf();
1321 int set_a_break_pt_here = 9;
1322 SwapBuf();
1323 #endif
1324#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001325}
1326
reed@google.comac10a2d2010-12-22 21:39:39 +00001327void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1328 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1329
1330 if (NULL != rt && rt->needsResolve()) {
1331 GrAssert(kNone_MSFBO != fMSFBOType);
1332 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001333 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001334 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001335 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001336 rt->textureFBOID()));
1337 #if GR_COLLECT_STATS
1338 ++fStats.fRenderTargetChngCnt;
1339 #endif
1340 // make sure we go through set render target
1341 fHWDrawState.fRenderTarget = NULL;
1342
twiz@google.com0f31ca72011-03-18 17:38:11 +00001343 GrGLint left = 0;
1344 GrGLint right = texture->width();
reed@google.comac10a2d2010-12-22 21:39:39 +00001345 // we will have rendered to the top of the FBO.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001346 GrGLint top = texture->allocHeight();
1347 GrGLint bottom = texture->allocHeight() - texture->height();
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001348 if (kAppleES_MSFBO == fMSFBOType) {
1349 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001350 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001351 GR_GL(Scissor(left, bottom, right-left, top-bottom));
twiz@google.com59a190b2011-03-14 21:23:01 +00001352 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001353 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001354 fHWBounds.fScissorEnabled = true;
1355 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001356 if (kDesktopARB_MSFBO != fMSFBOType) {
1357 // these respect the scissor during the blit, so disable it.
1358 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1359 flushScissor(NULL);
1360 }
twiz@google.com59a190b2011-03-14 21:23:01 +00001361 GR_GL(BlitFramebuffer(left, bottom, right, top,
reed@google.comac10a2d2010-12-22 21:39:39 +00001362 left, bottom, right, top,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001363 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001364 }
1365 rt->setDirty(false);
reed@google.comac10a2d2010-12-22 21:39:39 +00001366 }
1367}
1368
twiz@google.com0f31ca72011-03-18 17:38:11 +00001369static const GrGLenum grToGLStencilFunc[] = {
1370 GR_GL_ALWAYS, // kAlways_StencilFunc
1371 GR_GL_NEVER, // kNever_StencilFunc
1372 GR_GL_GREATER, // kGreater_StencilFunc
1373 GR_GL_GEQUAL, // kGEqual_StencilFunc
1374 GR_GL_LESS, // kLess_StencilFunc
1375 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1376 GR_GL_EQUAL, // kEqual_StencilFunc,
1377 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001378};
1379GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1380GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1381GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1382GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1383GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1384GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1385GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1386GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1387GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1388
twiz@google.com0f31ca72011-03-18 17:38:11 +00001389static const GrGLenum grToGLStencilOp[] = {
1390 GR_GL_KEEP, // kKeep_StencilOp
1391 GR_GL_REPLACE, // kReplace_StencilOp
1392 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1393 GR_GL_INCR, // kIncClamp_StencilOp
1394 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1395 GR_GL_DECR, // kDecClamp_StencilOp
1396 GR_GL_ZERO, // kZero_StencilOp
1397 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001398};
1399GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1400GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1401GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1402GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1403GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1404GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1405GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1406GR_STATIC_ASSERT(6 == kZero_StencilOp);
1407GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1408
reed@google.comac10a2d2010-12-22 21:39:39 +00001409void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001410 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001411
1412 // use stencil for clipping if clipping is enabled and the clip
1413 // has been written into the stencil.
1414 bool stencilClip = fClipState.fClipInStencil &&
1415 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001416 bool stencilChange = fHWStencilClip != stencilClip ||
1417 fHWDrawState.fStencilSettings != *settings ||
1418 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1419 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001420
1421 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001422
bsalomon@google.comd302f142011-03-03 13:54:13 +00001423 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1424 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001425
bsalomon@google.comd302f142011-03-03 13:54:13 +00001426 if (settings->isDisabled()) {
1427 if (stencilClip) {
1428 settings = &gClipStencilSettings;
1429 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001430 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001431
1432 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001433 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001434 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001435 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001436 #if GR_DEBUG
1437 if (!fStencilWrapOpsSupport) {
1438 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1439 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1440 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1441 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1442 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1443 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1444 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1445 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1446 }
1447 #endif
1448 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1449 GrAssert(stencilBits ||
1450 (GrStencilSettings::gDisabled ==
1451 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001452 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1453 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001454
1455 unsigned int frontRef = settings->fFrontFuncRef;
1456 unsigned int frontMask = settings->fFrontFuncMask;
1457 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001458 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001459
1460 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1461
1462 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1463 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1464 } else {
1465 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1466
1467 ConvertStencilFuncAndMask(settings->fFrontFunc,
1468 stencilClip,
1469 clipStencilMask,
1470 userStencilMask,
1471 &frontRef,
1472 &frontMask);
1473 frontWriteMask &= userStencilMask;
1474 }
1475 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001476 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001477 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001478 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001479 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001480 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001481 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001482 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001483 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001484 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001485
1486 unsigned int backRef = settings->fBackFuncRef;
1487 unsigned int backMask = settings->fBackFuncMask;
1488 unsigned int backWriteMask = settings->fBackWriteMask;
1489
1490
1491 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1492 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1493 backFunc = grToGLStencilFunc[settings->fBackFunc];
1494 } else {
1495 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1496 ConvertStencilFuncAndMask(settings->fBackFunc,
1497 stencilClip,
1498 clipStencilMask,
1499 userStencilMask,
1500 &backRef,
1501 &backMask);
1502 backWriteMask &= userStencilMask;
1503 }
1504
twiz@google.com0f31ca72011-03-18 17:38:11 +00001505 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1506 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1507 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1508 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1509 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001510 grToGLStencilOp[settings->fFrontPassOp],
1511 grToGLStencilOp[settings->fFrontPassOp]));
1512
twiz@google.com0f31ca72011-03-18 17:38:11 +00001513 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001514 grToGLStencilOp[settings->fBackPassOp],
1515 grToGLStencilOp[settings->fBackPassOp]));
1516 } else {
1517 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1518 GR_GL(StencilMask(frontWriteMask));
1519 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1520 grToGLStencilOp[settings->fFrontPassOp],
1521 grToGLStencilOp[settings->fFrontPassOp]));
1522 }
1523 }
1524 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001525 fHWStencilClip = stencilClip;
1526 }
1527}
1528
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001529void GrGpuGL::flushAAState(GrPrimitiveType type) {
1530 if (GR_GL_SUPPORT_DESKTOP) {
1531 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1532 // smooth lines.
1533
1534 // we prefer smooth lines over multisampled lines
1535 // msaa should be disabled if drawing smooth lines.
1536 if (kLines_PrimitiveType == type) {
1537 if (!fHWAAState.fSmoothLineEnabled &&
1538 (kAntialias_StateBit & fCurrDrawState.fFlagBits)) {
1539 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1540 fHWAAState.fSmoothLineEnabled = true;
1541 } else if (fHWAAState.fSmoothLineEnabled &&
1542 !(kAntialias_StateBit & fCurrDrawState.fFlagBits)) {
1543 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1544 fHWAAState.fSmoothLineEnabled = false;
1545 }
1546 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1547 fHWAAState.fMSAAEnabled) {
1548 GR_GL(Disable(GR_GL_MULTISAMPLE));
1549 fHWAAState.fMSAAEnabled = false;
1550 }
1551 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1552 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1553 fHWAAState.fMSAAEnabled) {
1554 if (fHWAAState.fMSAAEnabled) {
1555 GR_GL(Disable(GR_GL_MULTISAMPLE));
1556 fHWAAState.fMSAAEnabled = false;
1557 } else {
1558 GR_GL(Enable(GR_GL_MULTISAMPLE));
1559 fHWAAState.fMSAAEnabled = true;
1560 }
1561 }
1562 }
1563}
1564
bsalomon@google.comffca4002011-02-22 20:34:01 +00001565bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001566
1567 // GrGpu::setupClipAndFlushState should have already checked this
1568 // and bailed if not true.
1569 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001570
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001571 for (int s = 0; s < kNumStages; ++s) {
1572 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001573
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001574 // bind texture and set sampler state
1575 if (usingTexture) {
1576 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001577
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001578 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001579 // if we created a rt/tex and rendered to it without using a
1580 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001581 // the last bound texture, but it needs resolving. So keep this
1582 // out of the "last != next" check.
1583 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001584
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001585 if (fHWDrawState.fTextures[s] != nextTexture) {
1586 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001587 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001588 #if GR_COLLECT_STATS
1589 ++fStats.fTextureChngCnt;
1590 #endif
1591 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1592 fHWDrawState.fTextures[s] = nextTexture;
1593 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001594
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001595 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001596 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001597 nextTexture->getTexParams();
1598 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001599
twiz@google.com0f31ca72011-03-18 17:38:11 +00001600 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1601 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001602 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001603 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001604 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001605 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001606
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001607 if (newTexParams.fFilter != oldTexParams.fFilter) {
1608 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001609 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1610 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001611 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001612 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1613 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001614 newTexParams.fFilter));
1615 }
1616 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1617 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001618 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1619 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001620 newTexParams.fWrapS));
1621 }
1622 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1623 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001624 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1625 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001626 newTexParams.fWrapT));
1627 }
1628 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001629
1630 // The texture matrix has to compensate for texture width/height
1631 // and NPOT-embedded-in-POT
1632 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001633 } else {
1634 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001635 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001636 }
1637 }
1638 }
1639
1640 flushRenderTarget();
1641
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001642 flushAAState(type);
1643
reed@google.comac10a2d2010-12-22 21:39:39 +00001644 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1645 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1646 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001647 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001648 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001649 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001650 }
1651 }
1652
bsalomon@google.comd302f142011-03-03 13:54:13 +00001653 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1654 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001655 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001656 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001657 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001658 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001659 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001660 }
1661 GR_GL(ColorMask(mask, mask, mask, mask));
1662 }
1663
reed@google.comac10a2d2010-12-22 21:39:39 +00001664 bool blendOff = canDisableBlend();
1665 if (fHWBlendDisabled != blendOff) {
1666 if (blendOff) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001667 GR_GL(Disable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001668 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001669 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001670 }
1671 fHWBlendDisabled = blendOff;
1672 }
1673
1674 if (!blendOff) {
1675 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1676 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1677 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1678 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1679 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1680 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1681 }
bsalomon@google.com080773c2011-03-15 19:09:25 +00001682 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1683 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1684 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1685
1686 float c[] = {
1687 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1688 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1689 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1690 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1691 };
1692 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1693 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1694 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001695 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001696
bsalomon@google.comd302f142011-03-03 13:54:13 +00001697 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1698 switch (fCurrDrawState.fDrawFace) {
1699 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001700 GR_GL(Enable(GR_GL_CULL_FACE));
1701 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001702 break;
1703 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001704 GR_GL(Enable(GR_GL_CULL_FACE));
1705 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001706 break;
1707 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001708 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001709 break;
1710 default:
1711 GrCrash("Unknown draw face.");
1712 }
1713 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1714 }
1715
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001716#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001717 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001718 for (int s = 0; s < kNumStages; ++s) {
1719 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1720 NULL == fCurrDrawState.fRenderTarget ||
1721 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001722 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001723 fCurrDrawState.fRenderTarget);
1724 }
1725#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001726
reed@google.comac10a2d2010-12-22 21:39:39 +00001727 flushStencil();
1728
bsalomon@google.comd302f142011-03-03 13:54:13 +00001729 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001730 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001731 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001732}
1733
1734void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001735 if (fHWGeometryState.fVertexBuffer != buffer) {
1736 fHWGeometryState.fArrayPtrsDirty = true;
1737 fHWGeometryState.fVertexBuffer = buffer;
1738 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001739}
1740
1741void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1742 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1743 buffer == fGeometrySrc.fVertexBuffer));
1744
1745 if (fHWGeometryState.fVertexBuffer == buffer) {
1746 // deleting bound buffer does implied bind to 0
1747 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001748 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001749 }
1750}
1751
1752void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1753 fGeometrySrc.fIndexBuffer = buffer;
1754}
1755
1756void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1757 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1758 buffer == fGeometrySrc.fIndexBuffer));
1759
1760 if (fHWGeometryState.fIndexBuffer == buffer) {
1761 // deleting bound buffer does implied bind to 0
1762 fHWGeometryState.fIndexBuffer = NULL;
1763 }
1764}
1765
reed@google.comac10a2d2010-12-22 21:39:39 +00001766void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1767 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001768 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001769 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001770 }
1771 if (fHWDrawState.fRenderTarget == renderTarget) {
1772 fHWDrawState.fRenderTarget = NULL;
1773 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001774}
1775
1776void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001777 for (int s = 0; s < kNumStages; ++s) {
1778 if (fCurrDrawState.fTextures[s] == texture) {
1779 fCurrDrawState.fTextures[s] = NULL;
1780 }
1781 if (fHWDrawState.fTextures[s] == texture) {
1782 // deleting bound texture does implied bind to 0
1783 fHWDrawState.fTextures[s] = NULL;
1784 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001785 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001786}
1787
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001788bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001789 GrGLenum* internalFormat,
1790 GrGLenum* format,
1791 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001792 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001793 case kRGBA_8888_GrPixelConfig:
1794 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001795 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001796 if (GR_GL_SUPPORT_ES) {
1797 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1798 // format for a BGRA is BGRA not RGBA (as on desktop)
1799 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1800 } else {
1801 *internalFormat = GR_GL_RGBA;
1802 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001803 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001804 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001805 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001806 *format = GR_GL_RGB;
1807 *internalFormat = GR_GL_RGB;
1808 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001809 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001810 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001811 *format = GR_GL_RGBA;
1812 *internalFormat = GR_GL_RGBA;
1813 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001814 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001815 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001816 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001817 *format = GR_GL_PALETTE8_RGBA8;
1818 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001819 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001820 } else {
1821 return false;
1822 }
1823 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001824 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001825 *format = GR_GL_ALPHA;
1826 *internalFormat = GR_GL_ALPHA;
1827 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001828 break;
1829 default:
1830 return false;
1831 }
1832 return true;
1833}
1834
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001835void GrGpuGL::setTextureUnit(int unit) {
1836 GrAssert(unit >= 0 && unit < kNumStages);
1837 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001838 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001839 fActiveTextureUnitIdx = unit;
1840 }
1841}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001842
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001843void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001844 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1845 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001846 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1847 }
1848}
1849
reed@google.comac10a2d2010-12-22 21:39:39 +00001850/* On ES the internalFormat and format must match for TexImage and we use
1851 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1852 decide the internalFormat. However, on ES internalFormat for
1853 RenderBufferStorage* has to be a specific format (not a base format like
1854 GL_RGBA).
1855 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001856bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001857 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001858 case kRGBA_8888_GrPixelConfig:
1859 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001860 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001861 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001862 return true;
1863 } else {
1864 return false;
1865 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001866 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001867 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1868 // with FBO extension desktop GL has
1869 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001870 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001871 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001872 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001873 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001874 return true;
1875 default:
1876 return false;
1877 }
1878}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001879
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001880void GrGpuGL::resetDirtyFlags() {
1881 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1882}
1883
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001884void GrGpuGL::setBuffers(bool indexed,
1885 int* extraVertexOffset,
1886 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001887
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001888 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001889
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001890 GrGLVertexBuffer* vbuf;
1891 switch (fGeometrySrc.fVertexSrc) {
1892 case kBuffer_GeometrySrcType:
1893 *extraVertexOffset = 0;
1894 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1895 break;
1896 case kArray_GeometrySrcType:
1897 case kReserved_GeometrySrcType:
1898 finalizeReservedVertices();
1899 *extraVertexOffset = fCurrPoolStartVertex;
1900 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1901 break;
1902 default:
1903 vbuf = NULL; // suppress warning
1904 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001905 }
1906
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001907 GrAssert(NULL != vbuf);
1908 GrAssert(!vbuf->isLocked());
1909 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001910 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001911 fHWGeometryState.fArrayPtrsDirty = true;
1912 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001913 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001914
1915 if (indexed) {
1916 GrAssert(NULL != extraIndexOffset);
1917
1918 GrGLIndexBuffer* ibuf;
1919 switch (fGeometrySrc.fIndexSrc) {
1920 case kBuffer_GeometrySrcType:
1921 *extraIndexOffset = 0;
1922 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1923 break;
1924 case kArray_GeometrySrcType:
1925 case kReserved_GeometrySrcType:
1926 finalizeReservedIndices();
1927 *extraIndexOffset = fCurrPoolStartIndex;
1928 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1929 break;
1930 default:
1931 ibuf = NULL; // suppress warning
1932 GrCrash("Unknown geometry src type!");
1933 }
1934
1935 GrAssert(NULL != ibuf);
1936 GrAssert(!ibuf->isLocked());
1937 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001938 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001939 fHWGeometryState.fIndexBuffer = ibuf;
1940 }
1941 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001942}