blob: cc9aacab4acdee1c77cd5043a395250792b2104e [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.com0650e812011-04-08 18:07:53 +00001529bool GrGpuGL::useSmoothLines() {
1530 // there is a conflict between using smooth lines and our use of
1531 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1532 // but not in a premul-alpha way. So we only use them when our alpha
1533 // is 0xff.
1534
1535 // TODO: write a smarter line frag shader.
1536
1537 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1538 canDisableBlend();
1539}
1540
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001541void GrGpuGL::flushAAState(GrPrimitiveType type) {
1542 if (GR_GL_SUPPORT_DESKTOP) {
1543 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1544 // smooth lines.
1545
1546 // we prefer smooth lines over multisampled lines
1547 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001548 if (GrIsPrimTypeLines(type)) {
1549 bool smooth = useSmoothLines();
1550 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001551 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1552 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001553 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001554 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1555 fHWAAState.fSmoothLineEnabled = false;
1556 }
1557 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1558 fHWAAState.fMSAAEnabled) {
1559 GR_GL(Disable(GR_GL_MULTISAMPLE));
1560 fHWAAState.fMSAAEnabled = false;
1561 }
1562 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1563 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1564 fHWAAState.fMSAAEnabled) {
1565 if (fHWAAState.fMSAAEnabled) {
1566 GR_GL(Disable(GR_GL_MULTISAMPLE));
1567 fHWAAState.fMSAAEnabled = false;
1568 } else {
1569 GR_GL(Enable(GR_GL_MULTISAMPLE));
1570 fHWAAState.fMSAAEnabled = true;
1571 }
1572 }
1573 }
1574}
1575
bsalomon@google.com0650e812011-04-08 18:07:53 +00001576void GrGpuGL::flushBlend(GrPrimitiveType type) {
1577 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1578 if (fHWBlendDisabled) {
1579 GR_GL(Enable(GR_GL_BLEND));
1580 fHWBlendDisabled = false;
1581 }
1582 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1583 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1584 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1585 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1586 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1587 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1588 }
1589 } else {
1590 bool blendOff = canDisableBlend();
1591 if (fHWBlendDisabled != blendOff) {
1592 if (blendOff) {
1593 GR_GL(Disable(GR_GL_BLEND));
1594 } else {
1595 GR_GL(Enable(GR_GL_BLEND));
1596 }
1597 fHWBlendDisabled = blendOff;
1598 }
1599 if (!blendOff) {
1600 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1601 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1602 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1603 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1604 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1605 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1606 }
1607 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1608 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1609 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1610
1611 float c[] = {
1612 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1613 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1614 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1615 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1616 };
1617 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1618 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1619 }
1620 }
1621 }
1622}
1623
bsalomon@google.comffca4002011-02-22 20:34:01 +00001624bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001625
1626 // GrGpu::setupClipAndFlushState should have already checked this
1627 // and bailed if not true.
1628 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001629
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001630 for (int s = 0; s < kNumStages; ++s) {
1631 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001632
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001633 // bind texture and set sampler state
1634 if (usingTexture) {
1635 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001636
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001637 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001638 // if we created a rt/tex and rendered to it without using a
1639 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001640 // the last bound texture, but it needs resolving. So keep this
1641 // out of the "last != next" check.
1642 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001643
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001644 if (fHWDrawState.fTextures[s] != nextTexture) {
1645 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001646 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001647 #if GR_COLLECT_STATS
1648 ++fStats.fTextureChngCnt;
1649 #endif
1650 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1651 fHWDrawState.fTextures[s] = nextTexture;
1652 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001653
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001654 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001655 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001656 nextTexture->getTexParams();
1657 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001658
twiz@google.com0f31ca72011-03-18 17:38:11 +00001659 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1660 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001661 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001662 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001663 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001664 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001665
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001666 if (newTexParams.fFilter != oldTexParams.fFilter) {
1667 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001668 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1669 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001670 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001671 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1672 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001673 newTexParams.fFilter));
1674 }
1675 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1676 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001677 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1678 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001679 newTexParams.fWrapS));
1680 }
1681 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1682 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001683 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1684 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001685 newTexParams.fWrapT));
1686 }
1687 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001688
1689 // The texture matrix has to compensate for texture width/height
1690 // and NPOT-embedded-in-POT
1691 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001692 } else {
1693 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001694 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001695 }
1696 }
1697 }
1698
1699 flushRenderTarget();
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001700 flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001701 flushBlend(type);
1702
reed@google.comac10a2d2010-12-22 21:39:39 +00001703 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1704 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1705 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001706 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001707 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001708 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001709 }
1710 }
1711
bsalomon@google.comd302f142011-03-03 13:54:13 +00001712 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1713 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001714 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001715 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001716 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001717 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001718 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001719 }
1720 GR_GL(ColorMask(mask, mask, mask, mask));
1721 }
1722
bsalomon@google.comd302f142011-03-03 13:54:13 +00001723 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1724 switch (fCurrDrawState.fDrawFace) {
1725 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001726 GR_GL(Enable(GR_GL_CULL_FACE));
1727 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001728 break;
1729 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001730 GR_GL(Enable(GR_GL_CULL_FACE));
1731 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001732 break;
1733 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001734 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001735 break;
1736 default:
1737 GrCrash("Unknown draw face.");
1738 }
1739 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1740 }
1741
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001742#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001743 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001744 for (int s = 0; s < kNumStages; ++s) {
1745 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1746 NULL == fCurrDrawState.fRenderTarget ||
1747 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001748 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001749 fCurrDrawState.fRenderTarget);
1750 }
1751#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001752
reed@google.comac10a2d2010-12-22 21:39:39 +00001753 flushStencil();
1754
bsalomon@google.comd302f142011-03-03 13:54:13 +00001755 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001756 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001757 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001758}
1759
1760void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001761 if (fHWGeometryState.fVertexBuffer != buffer) {
1762 fHWGeometryState.fArrayPtrsDirty = true;
1763 fHWGeometryState.fVertexBuffer = buffer;
1764 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001765}
1766
1767void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001768 if (fHWGeometryState.fVertexBuffer == buffer) {
1769 // deleting bound buffer does implied bind to 0
1770 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001771 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001772 }
1773}
1774
1775void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1776 fGeometrySrc.fIndexBuffer = buffer;
1777}
1778
1779void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001780 if (fHWGeometryState.fIndexBuffer == buffer) {
1781 // deleting bound buffer does implied bind to 0
1782 fHWGeometryState.fIndexBuffer = NULL;
1783 }
1784}
1785
reed@google.comac10a2d2010-12-22 21:39:39 +00001786void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1787 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001788 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001789 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001790 }
1791 if (fHWDrawState.fRenderTarget == renderTarget) {
1792 fHWDrawState.fRenderTarget = NULL;
1793 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001794}
1795
1796void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001797 for (int s = 0; s < kNumStages; ++s) {
1798 if (fCurrDrawState.fTextures[s] == texture) {
1799 fCurrDrawState.fTextures[s] = NULL;
1800 }
1801 if (fHWDrawState.fTextures[s] == texture) {
1802 // deleting bound texture does implied bind to 0
1803 fHWDrawState.fTextures[s] = NULL;
1804 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001805 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001806}
1807
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001808bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001809 GrGLenum* internalFormat,
1810 GrGLenum* format,
1811 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001812 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001813 case kRGBA_8888_GrPixelConfig:
1814 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001815 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001816 if (GR_GL_SUPPORT_ES) {
1817 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1818 // format for a BGRA is BGRA not RGBA (as on desktop)
1819 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1820 } else {
1821 *internalFormat = GR_GL_RGBA;
1822 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001823 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001824 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001825 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001826 *format = GR_GL_RGB;
1827 *internalFormat = GR_GL_RGB;
1828 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001829 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001830 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001831 *format = GR_GL_RGBA;
1832 *internalFormat = GR_GL_RGBA;
1833 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001834 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001835 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001836 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001837 *format = GR_GL_PALETTE8_RGBA8;
1838 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001839 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001840 } else {
1841 return false;
1842 }
1843 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001844 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001845 *format = GR_GL_ALPHA;
1846 *internalFormat = GR_GL_ALPHA;
1847 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001848 break;
1849 default:
1850 return false;
1851 }
1852 return true;
1853}
1854
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001855void GrGpuGL::setTextureUnit(int unit) {
1856 GrAssert(unit >= 0 && unit < kNumStages);
1857 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001858 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001859 fActiveTextureUnitIdx = unit;
1860 }
1861}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001862
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001863void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001864 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1865 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001866 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1867 }
1868}
1869
reed@google.comac10a2d2010-12-22 21:39:39 +00001870/* On ES the internalFormat and format must match for TexImage and we use
1871 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1872 decide the internalFormat. However, on ES internalFormat for
1873 RenderBufferStorage* has to be a specific format (not a base format like
1874 GL_RGBA).
1875 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001876bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001877 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001878 case kRGBA_8888_GrPixelConfig:
1879 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001880 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001881 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001882 return true;
1883 } else {
1884 return false;
1885 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001886 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001887 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1888 // with FBO extension desktop GL has
1889 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001890 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001891 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001892 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001893 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001894 return true;
1895 default:
1896 return false;
1897 }
1898}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001899
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001900void GrGpuGL::resetDirtyFlags() {
1901 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1902}
1903
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001904void GrGpuGL::setBuffers(bool indexed,
1905 int* extraVertexOffset,
1906 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001907
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001908 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001909
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001910 GrGLVertexBuffer* vbuf;
1911 switch (fGeometrySrc.fVertexSrc) {
1912 case kBuffer_GeometrySrcType:
1913 *extraVertexOffset = 0;
1914 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1915 break;
1916 case kArray_GeometrySrcType:
1917 case kReserved_GeometrySrcType:
1918 finalizeReservedVertices();
1919 *extraVertexOffset = fCurrPoolStartVertex;
1920 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1921 break;
1922 default:
1923 vbuf = NULL; // suppress warning
1924 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001925 }
1926
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001927 GrAssert(NULL != vbuf);
1928 GrAssert(!vbuf->isLocked());
1929 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001930 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001931 fHWGeometryState.fArrayPtrsDirty = true;
1932 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001933 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001934
1935 if (indexed) {
1936 GrAssert(NULL != extraIndexOffset);
1937
1938 GrGLIndexBuffer* ibuf;
1939 switch (fGeometrySrc.fIndexSrc) {
1940 case kBuffer_GeometrySrcType:
1941 *extraIndexOffset = 0;
1942 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1943 break;
1944 case kArray_GeometrySrcType:
1945 case kReserved_GeometrySrcType:
1946 finalizeReservedIndices();
1947 *extraIndexOffset = fCurrPoolStartIndex;
1948 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1949 break;
1950 default:
1951 ibuf = NULL; // suppress warning
1952 GrCrash("Unknown geometry src type!");
1953 }
1954
1955 GrAssert(NULL != ibuf);
1956 GrAssert(!ibuf->isLocked());
1957 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001958 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001959 fHWGeometryState.fIndexBuffer = ibuf;
1960 }
1961 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001962}