blob: 7e88edeffd553c0f74ece7ce4e1cb078f36b8fde [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
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000410 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
411
reed@google.comac10a2d2010-12-22 21:39:39 +0000412 /* The iPhone 4 has a restriction that for an FBO with texture color
413 attachment with height <= 8 then the width must be <= height. Here
414 we look for such a limitation.
415 */
416 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000417 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000418 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000419 // fbo_test creates FBOs with texture bound to the color attachment
420 maxRenderSize = GrMin(maxRenderSize, fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000421
reed@google.comeeeb5a02010-12-23 15:12:59 +0000422 if (gPrintStartupSpew) {
423 GrPrintf("Small height FBO texture experiments\n");
424 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000425
twiz@google.com0f31ca72011-03-18 17:38:11 +0000426 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
427 GrGLuint w = maxRenderSize;
428 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000429 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000430 if (gPrintStartupSpew) {
431 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
432 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000433 fMinRenderTargetHeight = i;
434 break;
435 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000436 if (gPrintStartupSpew) {
437 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
438 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000439 }
440 }
441 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
442
reed@google.comeeeb5a02010-12-23 15:12:59 +0000443 if (gPrintStartupSpew) {
444 GrPrintf("Small width FBO texture experiments\n");
445 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000446 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000447 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
448 GrGLuint w = i;
449 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000450 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000451 if (gPrintStartupSpew) {
452 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
453 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000454 fMinRenderTargetWidth = i;
455 break;
456 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000457 if (gPrintStartupSpew) {
458 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
459 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000460 }
461 }
462 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
reed@google.comac10a2d2010-12-22 21:39:39 +0000463}
464
465GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000466}
467
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000468void GrGpuGL::resetContext() {
469 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000470 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000471 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000472
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000473 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000474 GR_GL(Disable(GR_GL_DEPTH_TEST));
475 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000476
twiz@google.com0f31ca72011-03-18 17:38:11 +0000477 GR_GL(Disable(GR_GL_CULL_FACE));
478 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000479 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000480
twiz@google.com0f31ca72011-03-18 17:38:11 +0000481 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000482 if (GR_GL_SUPPORT_DESKTOP) {
483 GR_GL(Disable(GR_GL_LINE_SMOOTH));
484 GR_GL(Disable(GR_GL_POINT_SMOOTH));
485 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000486 fHWAAState.fMSAAEnabled = false;
487 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000488 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000489
twiz@google.com0f31ca72011-03-18 17:38:11 +0000490 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000491 fHWDrawState.fFlagBits = 0;
492
reed@google.comac10a2d2010-12-22 21:39:39 +0000493 // we only ever use lines in hairline mode
494 GR_GL(LineWidth(1));
495
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000496 // invalid
497 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000498
reed@google.comac10a2d2010-12-22 21:39:39 +0000499 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000500 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
501 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000502
503 fHWDrawState.fBlendConstant = 0x00000000;
504 GR_GL(BlendColor(0,0,0,0));
505
reed@google.comac10a2d2010-12-22 21:39:39 +0000506 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000507
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000508 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000509
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000510 for (int s = 0; s < kNumStages; ++s) {
511 fHWDrawState.fTextures[s] = NULL;
512 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
513 -GR_ScalarMax,
514 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000515
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000516 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000517 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000518
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000519 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000520 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000521 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000522 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000523
bsalomon@google.comd302f142011-03-03 13:54:13 +0000524 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000525 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000526 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000527
528 fHWGeometryState.fIndexBuffer = NULL;
529 fHWGeometryState.fVertexBuffer = NULL;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000530 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
531 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000532 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000533
twiz@google.com0f31ca72011-03-18 17:38:11 +0000534 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000535 fHWDrawState.fRenderTarget = NULL;
536}
537
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000538GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
539
540 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
541 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
542 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
543 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
544
545 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
546 if (isRenderTarget) {
547 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
548 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
549 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
550 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
551 } else {
552 GrAssert(!isTexture); // this should have been filtered by GrContext
553 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
554 }
555 } else {
556 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
557 }
558 // we don't know what the RB ids are without glGets and we don't care
559 // since we aren't responsible for deleting them.
560 rtIDs.fStencilRenderbufferID = 0;
561 rtIDs.fMSColorRenderbufferID = 0;
562
563 rtIDs.fOwnIDs = false;
564 } else {
565 rtIDs.reset();
566 }
567
568 if (isTexture) {
569 GrGLTexture::GLTextureDesc texDesc;
570 GrGLenum dontCare;
571 if (!canBeTexture(desc.fConfig, &dontCare,
572 &texDesc.fUploadFormat,
573 &texDesc.fUploadType)) {
574 return NULL;
575 }
576
577 GrGLTexture::TexParams params;
578
579 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
580 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
581
582 texDesc.fFormat = texDesc.fFormat;
583 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
584 texDesc.fStencilBits = desc.fStencilBits;
585 texDesc.fTextureID = desc.fPlatformTexture;
586 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
587 texDesc.fOwnsID = false;
588
589 params.invalidate(); // rather than do glGets.
590
591 return new GrGLTexture(this, texDesc, rtIDs, params);
592 } else {
593 GrGLIRect viewport;
594 viewport.fLeft = 0;
595 viewport.fBottom = 0;
596 viewport.fWidth = desc.fWidth;
597 viewport.fHeight = desc.fHeight;
598
599 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
600 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
601 viewport, NULL);
602 }
603}
604
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000605GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
reed@google.comac10a2d2010-12-22 21:39:39 +0000606 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000607 int stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000608 bool isMultisampled,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000609 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000610 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000611 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
612 rtIDs.fStencilRenderbufferID = 0;
613 rtIDs.fMSColorRenderbufferID = 0;
614 rtIDs.fTexFBOID = 0;
615 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000616 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000617
618 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000619 viewport.fLeft = 0;
620 viewport.fBottom = 0;
621 viewport.fWidth = width;
622 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000623
twiz@google.com0f31ca72011-03-18 17:38:11 +0000624 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
625 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000626
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000627 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
628 isMultisampled, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000629}
630
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000631GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000632
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000633 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000634
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000635 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000636 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
637 rtIDs.fMSColorRenderbufferID = 0;
638 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000639
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000640 GrGLIRect viewport;
641 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000642 GrGLuint stencilBits;
643 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000644
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000645 GrGLint samples;
646 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
647
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000648 rtIDs.fOwnIDs = false;
649
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000650 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
651 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000652}
653
bsalomon@google.com5782d712011-01-21 21:03:59 +0000654///////////////////////////////////////////////////////////////////////////////
655
twiz@google.com0f31ca72011-03-18 17:38:11 +0000656static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000657
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000658struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000659 GrGLenum fEnum;
660 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000661 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000662};
663
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000664const StencilFormat* GrGLStencilFormats() {
665 // defines stencil formats from more to less preferred
666 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000667 {GR_GL_STENCIL_INDEX8, 8, false},
668 {GR_GL_STENCIL_INDEX16, 16, false},
669 {GR_GL_DEPTH24_STENCIL8, 8, true },
670 {GR_GL_STENCIL_INDEX4, 4, false},
671 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
672 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
673 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000674 };
675
676 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000677 {GR_GL_STENCIL_INDEX8, 8, false},
678 {GR_GL_DEPTH24_STENCIL8, 8, true },
679 {GR_GL_STENCIL_INDEX4, 4, false},
680 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000681 };
682
683 if (GR_GL_SUPPORT_DESKTOP) {
684 return desktopStencilFormats;
685 } else {
686 return esStencilFormats;
687 }
688}
689
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000690// good to set a break-point here to know when createTexture fails
691static GrTexture* return_null_texture() {
692// GrAssert(!"null texture");
693 return NULL;
694}
695
696#if GR_DEBUG
697static size_t as_size_t(int x) {
698 return x;
699}
700#endif
701
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000702GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
703 const void* srcData,
704 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000705
706#if GR_COLLECT_STATS
707 ++fStats.fTextureCreateCnt;
708#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000709
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000710 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000711
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000712 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000713 GR_GL_NEAREST,
714 GR_GL_CLAMP_TO_EDGE,
715 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000716 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000717
reed@google.comac10a2d2010-12-22 21:39:39 +0000718 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000719 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000720
721 glDesc.fContentWidth = desc.fWidth;
722 glDesc.fContentHeight = desc.fHeight;
723 glDesc.fAllocWidth = desc.fWidth;
724 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000725 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000726 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000727 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000728
729 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
730 if (!canBeTexture(desc.fFormat,
731 &internalFormat,
732 &glDesc.fUploadFormat,
733 &glDesc.fUploadType)) {
734 return return_null_texture();
735 }
736
737 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000738 GrGLint samples = fAASamples[desc.fAALevel];
reed@google.comac10a2d2010-12-22 21:39:39 +0000739 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
740 GrPrintf("AA RT requested but not supported on this platform.");
741 }
742
743 GR_GL(GenTextures(1, &glDesc.fTextureID));
744 if (!glDesc.fTextureID) {
745 return return_null_texture();
746 }
747
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000748 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000749
reed@google.com5e762232011-04-04 18:15:49 +0000750 // in case we need a temporary, trimmed copy of the src pixels
751 GrAutoSMalloc<128 * 128> trimStorage;
752
reed@google.comac10a2d2010-12-22 21:39:39 +0000753 /*
754 * check if our srcData has extra bytes past each row. If so, we need
755 * to trim those off here, since GL doesn't let us pass the rowBytes as
756 * a parameter to glTexImage2D
757 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000758 if (GR_GL_SUPPORT_DESKTOP) {
759 if (srcData) {
760 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
761 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000762 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000763 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000764 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
765 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000766 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000767 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000768 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000769 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000770 for (uint32_t y = 0; y < desc.fHeight; y++) {
771 memcpy(dst, src, trimRowBytes);
772 src += rowBytes;
773 dst += trimRowBytes;
774 }
775 // now point srcData to our trimmed version
776 srcData = trimStorage.get();
777 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000778 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000779
reed@google.comac10a2d2010-12-22 21:39:39 +0000780 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000781 if (!this->npotRenderTargetSupport()) {
782 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
783 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
784 }
785
reed@google.comac10a2d2010-12-22 21:39:39 +0000786 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
787 glDesc.fAllocWidth);
788 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
789 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000790 } else if (!this->npotTextureSupport()) {
791 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
792 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000793 }
794
twiz@google.com0f31ca72011-03-18 17:38:11 +0000795 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
796 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
797 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000798 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000799 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
800 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000801 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000802 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
803 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000804 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000805 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
806 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000807 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000808
twiz@google.com0f31ca72011-03-18 17:38:11 +0000809 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000810 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000811 supports8BitPalette()) {
812 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
813 GrAssert(desc.fWidth == glDesc.fAllocWidth);
814 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000815 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
816 kColorTableSize;
817 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000818 glDesc.fAllocWidth, glDesc.fAllocHeight,
819 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000820 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000821 } else {
822 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
823 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000824 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000825 glDesc.fAllocWidth, glDesc.fAllocHeight,
826 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000827 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000828 desc.fHeight, glDesc.fUploadFormat,
829 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000830 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000831
832 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
833 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
834 uint32_t maxTexels = extraW * extraH;
835 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
836 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
837
838 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
839
840 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
841 if (extraH) {
842 uint8_t* lastRowStart = (uint8_t*) srcData +
843 (desc.fHeight - 1) * rowSize;
844 uint8_t* extraRowStart = (uint8_t*)texels.get();
845
846 for (uint32_t i = 0; i < extraH; ++i) {
847 memcpy(extraRowStart, lastRowStart, rowSize);
848 extraRowStart += rowSize;
849 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000850 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000851 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
852 texels.get()));
853 }
854 if (extraW) {
855 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
856 uint8_t* extraTexel = (uint8_t*)texels.get();
857 for (uint32_t j = 0; j < desc.fHeight; ++j) {
858 for (uint32_t i = 0; i < extraW; ++i) {
859 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
860 extraTexel += glDesc.fUploadByteCount;
861 }
862 edgeTexel += rowSize;
863 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000864 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000865 desc.fHeight, glDesc.fUploadFormat,
866 glDesc.fUploadType, texels.get()));
867 }
868 if (extraW && extraH) {
869 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
870 - glDesc.fUploadByteCount;
871 uint8_t* extraTexel = (uint8_t*)texels.get();
872 for (uint32_t i = 0; i < extraW*extraH; ++i) {
873 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
874 extraTexel += glDesc.fUploadByteCount;
875 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000876 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000877 extraW, extraH, glDesc.fUploadFormat,
878 glDesc.fUploadType, texels.get()));
879 }
880
881 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000882 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000883 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
884 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000885 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000886 }
887 }
888
889 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
890
891 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
892 rtIDs.fStencilRenderbufferID = 0;
893 rtIDs.fMSColorRenderbufferID = 0;
894 rtIDs.fRTFBOID = 0;
895 rtIDs.fTexFBOID = 0;
896 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000897 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000898
899 if (renderTarget) {
900#if GR_COLLECT_STATS
901 ++fStats.fRenderTargetCreateCnt;
902#endif
903 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000904 GrGLenum status;
905 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000906
907 // If need have both RT flag and srcData we have
908 // to invert the data before uploading because FBO
909 // will be rendered bottom up
910 GrAssert(NULL == srcData);
911 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
912
twiz@google.com59a190b2011-03-14 21:23:01 +0000913 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000914 GrAssert(rtIDs.fTexFBOID);
915
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000916 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000917 // to one and then resolve to the texture bound to the other.
918 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000919 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000920 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000921 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
923 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000924 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000925 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000926 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
927 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000928 return return_null_texture();
929 }
930 } else {
931 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
932 }
bsalomon@google.comf6a7c112011-03-24 16:14:10 +0000933 if (!(kNoStencil_TextureFlag & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000934 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000935 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000936 }
937
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000938 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000939 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000940 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000941 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000942
twiz@google.com0f31ca72011-03-18 17:38:11 +0000943 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000944
945 const StencilFormat* stencilFormats = GrGLStencilFormats();
946 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000947 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000948 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000949 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000950 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000951 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000952 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000953 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000954 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000955 glDesc.fAllocWidth,
956 glDesc.fAllocHeight));
957 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000958 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000959 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000960 glDesc.fAllocWidth,
961 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000962 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000963 err = GrGLGetGLInterface()->fGetError();
964 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000965 continue;
966 }
967 }
968 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
969 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000970 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000971 rtIDs.fMSColorRenderbufferID));
972 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000973 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000974 samples,
975 msColorRenderbufferFormat,
976 glDesc.fAllocWidth,
977 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000978 err = GrGLGetGLInterface()->fGetError();
979 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000980 continue;
981 }
982 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000983 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000984
985#if GR_COLLECT_STATS
986 ++fStats.fRenderTargetChngCnt;
987#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000988 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
989 GR_GL_COLOR_ATTACHMENT0,
990 GR_GL_TEXTURE_2D,
991 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000992 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000993 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
994 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000995 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
996 status, desc.fWidth, desc.fHeight);
997 continue;
998 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000999 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001000 #if GR_COLLECT_STATS
1001 ++fStats.fRenderTargetChngCnt;
1002 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001003 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1004 GR_GL_COLOR_ATTACHMENT0,
1005 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001006 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001007
1008 }
1009 if (rtIDs.fStencilRenderbufferID) {
1010 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001011 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1012 GR_GL_STENCIL_ATTACHMENT,
1013 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001014 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001015 // if it is a packed format bind to depth also, otherwise
1016 // we may get an unsupported fbo completeness result
1017 if (stencilFormats[i].fPacked) {
1018 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1019 GR_GL_DEPTH_ATTACHMENT,
1020 GR_GL_RENDERBUFFER,
1021 rtIDs.fStencilRenderbufferID));
1022 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001023 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001024 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001025
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001026 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001027 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1028 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001029 // undo the depth bind
1030 if (rtIDs.fStencilRenderbufferID &&
1031 stencilFormats[i].fPacked) {
1032 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1033 GR_GL_DEPTH_ATTACHMENT,
1034 GR_GL_RENDERBUFFER,
1035 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001036 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001037 continue;
1038 }
1039 // we're successful!
1040 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001041 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001042 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001043 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001044 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001045 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001046 }
1047 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001048 break;
1049 }
1050 if (failed) {
1051 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001052 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001053 }
1054 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001055 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001056 }
1057 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001058 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001059 }
1060 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001061 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001062 }
1063 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1064 return return_null_texture();
1065 }
1066 }
1067#ifdef TRACE_TEXTURE_CREATION
1068 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1069 tex->fTextureID, width, height, tex->fUploadByteCount);
1070#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001071 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001072
1073 if (0 != rtIDs.fTexFBOID) {
1074 GrRenderTarget* rt = tex->asRenderTarget();
1075 // We've messed with FBO state but may not have set the correct viewport
1076 // so just dirty the rendertarget state to force a resend.
1077 fHWDrawState.fRenderTarget = NULL;
1078
1079 // clear the new stencil buffer if we have one
bsalomon@google.comf6a7c112011-03-24 16:14:10 +00001080 if (!(desc.fFlags & kNoStencil_TextureFlag)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001081 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1082 fCurrDrawState.fRenderTarget = rt;
1083 eraseStencil(0, ~0);
1084 fCurrDrawState.fRenderTarget = rtSave;
1085 }
1086 }
1087 return tex;
1088}
1089
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001090GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001091 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001092 GR_GL(GenBuffers(1, &id));
1093 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001094 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001095 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001096 GrGLClearErr();
1097 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001098 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1099 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1100 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001101 GR_GL(DeleteBuffers(1, &id));
1102 // deleting bound buffer does implicit bind to 0
1103 fHWGeometryState.fVertexBuffer = NULL;
1104 return NULL;
1105 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001106 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001107 size, dynamic);
1108 fHWGeometryState.fVertexBuffer = vertexBuffer;
1109 return vertexBuffer;
1110 }
1111 return NULL;
1112}
1113
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001114GrIndexBuffer* GrGpuGL::createIndexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001115 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001116 GR_GL(GenBuffers(1, &id));
1117 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001118 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001119 GrGLClearErr();
1120 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001121 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1122 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1123 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001124 GR_GL(DeleteBuffers(1, &id));
1125 // deleting bound buffer does implicit bind to 0
1126 fHWGeometryState.fIndexBuffer = NULL;
1127 return NULL;
1128 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001129 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001130 size, dynamic);
1131 fHWGeometryState.fIndexBuffer = indexBuffer;
1132 return indexBuffer;
1133 }
1134 return NULL;
1135}
1136
reed@google.comac10a2d2010-12-22 21:39:39 +00001137void GrGpuGL::flushScissor(const GrIRect* rect) {
1138 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001139 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001140 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001141
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001142 GrGLIRect scissor;
1143 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001144 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001145 rect->width(), rect->height());
1146 if (scissor.contains(vp)) {
1147 rect = NULL;
1148 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001149 }
1150
1151 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001152 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001153 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001154 fHWBounds.fScissorRect = scissor;
1155 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001157 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001158 fHWBounds.fScissorEnabled = true;
1159 }
1160 } else {
1161 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001162 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001163 fHWBounds.fScissorEnabled = false;
1164 }
1165 }
1166}
1167
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001168void GrGpuGL::eraseColorHelper(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001169 if (NULL == fCurrDrawState.fRenderTarget) {
1170 return;
1171 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001172 flushRenderTarget();
1173 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001174 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001175 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001176 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001177 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001178 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001179 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1180 GrColorUnpackG(color)/255.f,
1181 GrColorUnpackB(color)/255.f,
1182 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001183 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001184}
1185
1186void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001187 if (NULL == fCurrDrawState.fRenderTarget) {
1188 return;
1189 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001190 flushRenderTarget();
1191 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001192 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001193 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001194 }
1195 GR_GL(StencilMask(mask));
1196 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001197 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001198 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001199}
1200
bsalomon@google.comd302f142011-03-03 13:54:13 +00001201void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001202 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001203#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001204 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001205 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001206 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001207#else
1208 // we could just clear the clip bit but when we go through
1209 // angle a partial stencil mask will cause clears to be
1210 // turned into draws. Our contract on GrDrawTarget says that
1211 // changing the clip between stencil passes may or may not
1212 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001213 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001214#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001215 flushRenderTarget();
1216 flushScissor(&rect);
1217 GR_GL(StencilMask(clipStencilMask));
1218 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001219 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001220 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001221}
1222
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001223void GrGpuGL::forceRenderTargetFlushHelper() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001224 flushRenderTarget();
1225}
1226
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001227bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1228 int left, int top, int width, int height,
1229 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001230 GrGLenum internalFormat; // we don't use this for glReadPixels
1231 GrGLenum format;
1232 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001233 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1234 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001235 }
1236 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1237 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1238 switch (tgt->getResolveType()) {
1239 case GrGLRenderTarget::kCantResolve_ResolveType:
1240 return false;
1241 case GrGLRenderTarget::kAutoResolves_ResolveType:
1242 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1243 fCurrDrawState.fRenderTarget = target;
1244 flushRenderTarget();
1245 break;
1246 case GrGLRenderTarget::kCanResolve_ResolveType:
1247 resolveRenderTarget(tgt);
1248 // we don't track the state of the READ FBO ID.
1249 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1250 break;
1251 default:
1252 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001253 }
1254
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001255 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001256
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001257 // the read rect is viewport-relative
1258 GrGLIRect readRect;
1259 readRect.setRelativeTo(glvp, left, top, width, height);
1260 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001261 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001262 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001263
1264 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1265 // API presents top-to-bottom
1266 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001267 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001268 GrAutoMalloc rowStorage(stride);
1269 void* tmp = rowStorage.get();
1270
1271 const int halfY = height >> 1;
1272 char* top = reinterpret_cast<char*>(buffer);
1273 char* bottom = top + (height - 1) * stride;
1274 for (int y = 0; y < halfY; y++) {
1275 memcpy(tmp, top, stride);
1276 memcpy(top, bottom, stride);
1277 memcpy(bottom, tmp, stride);
1278 top += stride;
1279 bottom -= stride;
1280 }
1281 }
1282 return true;
1283}
1284
1285void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001286
1287 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1288
reed@google.comac10a2d2010-12-22 21:39:39 +00001289 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1290 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001291 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001292 #if GR_COLLECT_STATS
1293 ++fStats.fRenderTargetChngCnt;
1294 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001295 rt->flagAsNeedingResolve();
reed@google.comac10a2d2010-12-22 21:39:39 +00001296 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001297 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1298 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001299 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1300 }
1301 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001302 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001303 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001304 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001305 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001306 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001307 fHWBounds.fViewportRect = vp;
1308 }
1309 }
1310}
1311
twiz@google.com0f31ca72011-03-18 17:38:11 +00001312GrGLenum gPrimitiveType2GLMode[] = {
1313 GR_GL_TRIANGLES,
1314 GR_GL_TRIANGLE_STRIP,
1315 GR_GL_TRIANGLE_FAN,
1316 GR_GL_POINTS,
1317 GR_GL_LINES,
1318 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001319};
1320
bsalomon@google.comd302f142011-03-03 13:54:13 +00001321#define SWAP_PER_DRAW 0
1322
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001323#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001324 #if GR_MAC_BUILD
1325 #include <AGL/agl.h>
1326 #elif GR_WIN32_BUILD
1327 void SwapBuf() {
1328 DWORD procID = GetCurrentProcessId();
1329 HWND hwnd = GetTopWindow(GetDesktopWindow());
1330 while(hwnd) {
1331 DWORD wndProcID = 0;
1332 GetWindowThreadProcessId(hwnd, &wndProcID);
1333 if(wndProcID == procID) {
1334 SwapBuffers(GetDC(hwnd));
1335 }
1336 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1337 }
1338 }
1339 #endif
1340#endif
1341
bsalomon@google.comffca4002011-02-22 20:34:01 +00001342void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001343 uint32_t startVertex,
1344 uint32_t startIndex,
1345 uint32_t vertexCount,
1346 uint32_t indexCount) {
1347 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1348
twiz@google.com0f31ca72011-03-18 17:38:11 +00001349 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001350
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001351 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1352 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1353
1354 // our setupGeometry better have adjusted this to zero since
1355 // DrawElements always draws from the begining of the arrays for idx 0.
1356 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001357
1358 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001359 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001360#if SWAP_PER_DRAW
1361 glFlush();
1362 #if GR_MAC_BUILD
1363 aglSwapBuffers(aglGetCurrentContext());
1364 int set_a_break_pt_here = 9;
1365 aglSwapBuffers(aglGetCurrentContext());
1366 #elif GR_WIN32_BUILD
1367 SwapBuf();
1368 int set_a_break_pt_here = 9;
1369 SwapBuf();
1370 #endif
1371#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001372}
1373
bsalomon@google.comffca4002011-02-22 20:34:01 +00001374void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001375 uint32_t startVertex,
1376 uint32_t vertexCount) {
1377 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1378
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001379 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1380
1381 // our setupGeometry better have adjusted this to zero.
1382 // DrawElements doesn't take an offset so we always adjus the startVertex.
1383 GrAssert(0 == startVertex);
1384
1385 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1386 // account for startVertex in the DrawElements case. So we always
1387 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001388 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001389#if SWAP_PER_DRAW
1390 glFlush();
1391 #if GR_MAC_BUILD
1392 aglSwapBuffers(aglGetCurrentContext());
1393 int set_a_break_pt_here = 9;
1394 aglSwapBuffers(aglGetCurrentContext());
1395 #elif GR_WIN32_BUILD
1396 SwapBuf();
1397 int set_a_break_pt_here = 9;
1398 SwapBuf();
1399 #endif
1400#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001401}
1402
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001403void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001404
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001405 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001406 GrAssert(kNone_MSFBO != fMSFBOType);
1407 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001408 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001409 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001410 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001411 rt->textureFBOID()));
1412 #if GR_COLLECT_STATS
1413 ++fStats.fRenderTargetChngCnt;
1414 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001415 // make sure we go through flushRenderTarget() since we've modified
1416 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001417 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001418 const GrGLIRect& vp = rt->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001419
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001420 if (kAppleES_MSFBO == fMSFBOType) {
1421 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001422 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001423 GR_GL(Scissor(vp.fLeft, vp.fBottom,
1424 vp.fWidth, vp.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001425 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001426 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001427 fHWBounds.fScissorEnabled = true;
1428 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001429 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001430 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001431 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1432 flushScissor(NULL);
1433 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001434 int right = vp.fLeft + vp.fWidth;
1435 int top = vp.fBottom + vp.fHeight;
1436 GR_GL(BlitFramebuffer(vp.fLeft, vp.fBottom, right, top,
1437 vp.fLeft, vp.fBottom, right, top,
1438 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001439 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001440 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001441 }
1442}
1443
twiz@google.com0f31ca72011-03-18 17:38:11 +00001444static const GrGLenum grToGLStencilFunc[] = {
1445 GR_GL_ALWAYS, // kAlways_StencilFunc
1446 GR_GL_NEVER, // kNever_StencilFunc
1447 GR_GL_GREATER, // kGreater_StencilFunc
1448 GR_GL_GEQUAL, // kGEqual_StencilFunc
1449 GR_GL_LESS, // kLess_StencilFunc
1450 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1451 GR_GL_EQUAL, // kEqual_StencilFunc,
1452 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001453};
1454GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1455GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1456GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1457GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1458GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1459GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1460GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1461GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1462GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1463
twiz@google.com0f31ca72011-03-18 17:38:11 +00001464static const GrGLenum grToGLStencilOp[] = {
1465 GR_GL_KEEP, // kKeep_StencilOp
1466 GR_GL_REPLACE, // kReplace_StencilOp
1467 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1468 GR_GL_INCR, // kIncClamp_StencilOp
1469 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1470 GR_GL_DECR, // kDecClamp_StencilOp
1471 GR_GL_ZERO, // kZero_StencilOp
1472 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001473};
1474GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1475GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1476GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1477GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1478GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1479GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1480GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1481GR_STATIC_ASSERT(6 == kZero_StencilOp);
1482GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1483
reed@google.comac10a2d2010-12-22 21:39:39 +00001484void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001485 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001486
1487 // use stencil for clipping if clipping is enabled and the clip
1488 // has been written into the stencil.
1489 bool stencilClip = fClipState.fClipInStencil &&
1490 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001491 bool stencilChange = fHWStencilClip != stencilClip ||
1492 fHWDrawState.fStencilSettings != *settings ||
1493 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1494 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001495
1496 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001497
bsalomon@google.comd302f142011-03-03 13:54:13 +00001498 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1499 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001500
bsalomon@google.comd302f142011-03-03 13:54:13 +00001501 if (settings->isDisabled()) {
1502 if (stencilClip) {
1503 settings = &gClipStencilSettings;
1504 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001505 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001506
1507 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001508 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001509 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001510 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001511 #if GR_DEBUG
1512 if (!fStencilWrapOpsSupport) {
1513 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1514 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1515 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1516 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1517 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1518 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1519 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1520 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1521 }
1522 #endif
1523 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1524 GrAssert(stencilBits ||
1525 (GrStencilSettings::gDisabled ==
1526 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001527 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1528 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001529
1530 unsigned int frontRef = settings->fFrontFuncRef;
1531 unsigned int frontMask = settings->fFrontFuncMask;
1532 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001533 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001534
1535 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1536
1537 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1538 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1539 } else {
1540 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1541
1542 ConvertStencilFuncAndMask(settings->fFrontFunc,
1543 stencilClip,
1544 clipStencilMask,
1545 userStencilMask,
1546 &frontRef,
1547 &frontMask);
1548 frontWriteMask &= userStencilMask;
1549 }
1550 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001551 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001552 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001553 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001554 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001555 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001556 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001557 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001558 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001559 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001560
1561 unsigned int backRef = settings->fBackFuncRef;
1562 unsigned int backMask = settings->fBackFuncMask;
1563 unsigned int backWriteMask = settings->fBackWriteMask;
1564
1565
1566 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1567 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1568 backFunc = grToGLStencilFunc[settings->fBackFunc];
1569 } else {
1570 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1571 ConvertStencilFuncAndMask(settings->fBackFunc,
1572 stencilClip,
1573 clipStencilMask,
1574 userStencilMask,
1575 &backRef,
1576 &backMask);
1577 backWriteMask &= userStencilMask;
1578 }
1579
twiz@google.com0f31ca72011-03-18 17:38:11 +00001580 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1581 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1582 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1583 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1584 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001585 grToGLStencilOp[settings->fFrontPassOp],
1586 grToGLStencilOp[settings->fFrontPassOp]));
1587
twiz@google.com0f31ca72011-03-18 17:38:11 +00001588 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001589 grToGLStencilOp[settings->fBackPassOp],
1590 grToGLStencilOp[settings->fBackPassOp]));
1591 } else {
1592 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1593 GR_GL(StencilMask(frontWriteMask));
1594 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1595 grToGLStencilOp[settings->fFrontPassOp],
1596 grToGLStencilOp[settings->fFrontPassOp]));
1597 }
1598 }
1599 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001600 fHWStencilClip = stencilClip;
1601 }
1602}
1603
bsalomon@google.com0650e812011-04-08 18:07:53 +00001604bool GrGpuGL::useSmoothLines() {
1605 // there is a conflict between using smooth lines and our use of
1606 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1607 // but not in a premul-alpha way. So we only use them when our alpha
1608 // is 0xff.
1609
1610 // TODO: write a smarter line frag shader.
1611
1612 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1613 canDisableBlend();
1614}
1615
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001616void GrGpuGL::flushAAState(GrPrimitiveType type) {
1617 if (GR_GL_SUPPORT_DESKTOP) {
1618 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1619 // smooth lines.
1620
1621 // we prefer smooth lines over multisampled lines
1622 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001623 if (GrIsPrimTypeLines(type)) {
1624 bool smooth = useSmoothLines();
1625 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001626 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1627 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001628 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001629 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1630 fHWAAState.fSmoothLineEnabled = false;
1631 }
1632 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1633 fHWAAState.fMSAAEnabled) {
1634 GR_GL(Disable(GR_GL_MULTISAMPLE));
1635 fHWAAState.fMSAAEnabled = false;
1636 }
1637 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1638 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1639 fHWAAState.fMSAAEnabled) {
1640 if (fHWAAState.fMSAAEnabled) {
1641 GR_GL(Disable(GR_GL_MULTISAMPLE));
1642 fHWAAState.fMSAAEnabled = false;
1643 } else {
1644 GR_GL(Enable(GR_GL_MULTISAMPLE));
1645 fHWAAState.fMSAAEnabled = true;
1646 }
1647 }
1648 }
1649}
1650
bsalomon@google.com0650e812011-04-08 18:07:53 +00001651void GrGpuGL::flushBlend(GrPrimitiveType type) {
1652 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1653 if (fHWBlendDisabled) {
1654 GR_GL(Enable(GR_GL_BLEND));
1655 fHWBlendDisabled = false;
1656 }
1657 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1658 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1659 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1660 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1661 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1662 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1663 }
1664 } else {
1665 bool blendOff = canDisableBlend();
1666 if (fHWBlendDisabled != blendOff) {
1667 if (blendOff) {
1668 GR_GL(Disable(GR_GL_BLEND));
1669 } else {
1670 GR_GL(Enable(GR_GL_BLEND));
1671 }
1672 fHWBlendDisabled = blendOff;
1673 }
1674 if (!blendOff) {
1675 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1676 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1677 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1678 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1679 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1680 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1681 }
1682 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1683 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1684 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1685
1686 float c[] = {
1687 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1688 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1689 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1690 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1691 };
1692 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1693 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1694 }
1695 }
1696 }
1697}
1698
bsalomon@google.comffca4002011-02-22 20:34:01 +00001699bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001700
1701 // GrGpu::setupClipAndFlushState should have already checked this
1702 // and bailed if not true.
1703 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001704
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001705 for (int s = 0; s < kNumStages; ++s) {
1706 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001707
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001708 // bind texture and set sampler state
1709 if (usingTexture) {
1710 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001711
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001712 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001713 // if we created a rt/tex and rendered to it without using a
1714 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001715 // the last bound texture, but it needs resolving. So keep this
1716 // out of the "last != next" check.
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001717 GrGLRenderTarget* texRT =
1718 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1719 if (NULL != texRT) {
1720 resolveRenderTarget(texRT);
1721 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001722
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001723 if (fHWDrawState.fTextures[s] != nextTexture) {
1724 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001725 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001726 #if GR_COLLECT_STATS
1727 ++fStats.fTextureChngCnt;
1728 #endif
1729 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1730 fHWDrawState.fTextures[s] = nextTexture;
1731 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001732
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001733 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001734 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001735 nextTexture->getTexParams();
1736 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001737
twiz@google.com0f31ca72011-03-18 17:38:11 +00001738 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1739 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001740 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001741 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001742 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001743 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001744
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001745 if (newTexParams.fFilter != oldTexParams.fFilter) {
1746 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001747 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1748 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001749 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001750 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1751 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001752 newTexParams.fFilter));
1753 }
1754 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1755 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001756 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1757 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001758 newTexParams.fWrapS));
1759 }
1760 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1761 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001762 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1763 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001764 newTexParams.fWrapT));
1765 }
1766 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001767
1768 // The texture matrix has to compensate for texture width/height
1769 // and NPOT-embedded-in-POT
1770 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001771 } else {
1772 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001773 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001774 }
1775 }
1776 }
1777
1778 flushRenderTarget();
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001779 flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001780 flushBlend(type);
1781
reed@google.comac10a2d2010-12-22 21:39:39 +00001782 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1783 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1784 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001785 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001786 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001787 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001788 }
1789 }
1790
bsalomon@google.comd302f142011-03-03 13:54:13 +00001791 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1792 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001793 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001794 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001795 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001796 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001797 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001798 }
1799 GR_GL(ColorMask(mask, mask, mask, mask));
1800 }
1801
bsalomon@google.comd302f142011-03-03 13:54:13 +00001802 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1803 switch (fCurrDrawState.fDrawFace) {
1804 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001805 GR_GL(Enable(GR_GL_CULL_FACE));
1806 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001807 break;
1808 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001809 GR_GL(Enable(GR_GL_CULL_FACE));
1810 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001811 break;
1812 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001813 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001814 break;
1815 default:
1816 GrCrash("Unknown draw face.");
1817 }
1818 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1819 }
1820
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001821#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001822 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001823 for (int s = 0; s < kNumStages; ++s) {
1824 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1825 NULL == fCurrDrawState.fRenderTarget ||
1826 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001827 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001828 fCurrDrawState.fRenderTarget);
1829 }
1830#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001831
reed@google.comac10a2d2010-12-22 21:39:39 +00001832 flushStencil();
1833
bsalomon@google.comd302f142011-03-03 13:54:13 +00001834 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001835 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001836 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001837}
1838
1839void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001840 if (fHWGeometryState.fVertexBuffer != buffer) {
1841 fHWGeometryState.fArrayPtrsDirty = true;
1842 fHWGeometryState.fVertexBuffer = buffer;
1843 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001844}
1845
1846void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001847 if (fHWGeometryState.fVertexBuffer == buffer) {
1848 // deleting bound buffer does implied bind to 0
1849 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001850 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001851 }
1852}
1853
1854void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1855 fGeometrySrc.fIndexBuffer = buffer;
1856}
1857
1858void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001859 if (fHWGeometryState.fIndexBuffer == buffer) {
1860 // deleting bound buffer does implied bind to 0
1861 fHWGeometryState.fIndexBuffer = NULL;
1862 }
1863}
1864
reed@google.comac10a2d2010-12-22 21:39:39 +00001865void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1866 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001867 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001868 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001869 }
1870 if (fHWDrawState.fRenderTarget == renderTarget) {
1871 fHWDrawState.fRenderTarget = NULL;
1872 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001873}
1874
1875void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001876 for (int s = 0; s < kNumStages; ++s) {
1877 if (fCurrDrawState.fTextures[s] == texture) {
1878 fCurrDrawState.fTextures[s] = NULL;
1879 }
1880 if (fHWDrawState.fTextures[s] == texture) {
1881 // deleting bound texture does implied bind to 0
1882 fHWDrawState.fTextures[s] = NULL;
1883 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001884 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001885}
1886
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001887bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001888 GrGLenum* internalFormat,
1889 GrGLenum* format,
1890 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001891 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001892 case kRGBA_8888_GrPixelConfig:
1893 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001894 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001895 if (GR_GL_SUPPORT_ES) {
1896 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1897 // format for a BGRA is BGRA not RGBA (as on desktop)
1898 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1899 } else {
1900 *internalFormat = GR_GL_RGBA;
1901 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001902 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001903 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001904 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001905 *format = GR_GL_RGB;
1906 *internalFormat = GR_GL_RGB;
1907 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001908 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001909 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001910 *format = GR_GL_RGBA;
1911 *internalFormat = GR_GL_RGBA;
1912 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001913 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001914 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001915 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001916 *format = GR_GL_PALETTE8_RGBA8;
1917 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001918 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001919 } else {
1920 return false;
1921 }
1922 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001923 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001924 *format = GR_GL_ALPHA;
1925 *internalFormat = GR_GL_ALPHA;
1926 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001927 break;
1928 default:
1929 return false;
1930 }
1931 return true;
1932}
1933
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001934void GrGpuGL::setTextureUnit(int unit) {
1935 GrAssert(unit >= 0 && unit < kNumStages);
1936 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001937 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001938 fActiveTextureUnitIdx = unit;
1939 }
1940}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001941
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001942void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001943 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1944 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001945 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1946 }
1947}
1948
reed@google.comac10a2d2010-12-22 21:39:39 +00001949/* On ES the internalFormat and format must match for TexImage and we use
1950 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1951 decide the internalFormat. However, on ES internalFormat for
1952 RenderBufferStorage* has to be a specific format (not a base format like
1953 GL_RGBA).
1954 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001955bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001956 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001957 case kRGBA_8888_GrPixelConfig:
1958 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001959 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001960 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001961 return true;
1962 } else {
1963 return false;
1964 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001965 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001966 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1967 // with FBO extension desktop GL has
1968 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001969 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001970 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001971 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001972 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001973 return true;
1974 default:
1975 return false;
1976 }
1977}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001978
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001979void GrGpuGL::resetDirtyFlags() {
1980 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1981}
1982
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001983void GrGpuGL::setBuffers(bool indexed,
1984 int* extraVertexOffset,
1985 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001986
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001987 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001988
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001989 GrGLVertexBuffer* vbuf;
1990 switch (fGeometrySrc.fVertexSrc) {
1991 case kBuffer_GeometrySrcType:
1992 *extraVertexOffset = 0;
1993 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1994 break;
1995 case kArray_GeometrySrcType:
1996 case kReserved_GeometrySrcType:
1997 finalizeReservedVertices();
1998 *extraVertexOffset = fCurrPoolStartVertex;
1999 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2000 break;
2001 default:
2002 vbuf = NULL; // suppress warning
2003 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002004 }
2005
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002006 GrAssert(NULL != vbuf);
2007 GrAssert(!vbuf->isLocked());
2008 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002009 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002010 fHWGeometryState.fArrayPtrsDirty = true;
2011 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002012 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002013
2014 if (indexed) {
2015 GrAssert(NULL != extraIndexOffset);
2016
2017 GrGLIndexBuffer* ibuf;
2018 switch (fGeometrySrc.fIndexSrc) {
2019 case kBuffer_GeometrySrcType:
2020 *extraIndexOffset = 0;
2021 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2022 break;
2023 case kArray_GeometrySrcType:
2024 case kReserved_GeometrySrcType:
2025 finalizeReservedIndices();
2026 *extraIndexOffset = fCurrPoolStartIndex;
2027 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2028 break;
2029 default:
2030 ibuf = NULL; // suppress warning
2031 GrCrash("Unknown geometry src type!");
2032 }
2033
2034 GrAssert(NULL != ibuf);
2035 GrAssert(!ibuf->isLocked());
2036 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002037 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002038 fHWGeometryState.fIndexBuffer = ibuf;
2039 }
2040 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002041}