blob: e62949b14c6160938c4e508e648cbe86664e0013 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
bsalomon@google.com1da07462011-03-10 14:51:57 +00002 Copyright 2011 Google Inc.
reed@google.comac10a2d2010-12-22 21:39:39 +00003
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#include "GrGpuGL.h"
18#include "GrMemory.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000019
twiz@google.com0f31ca72011-03-18 17:38:11 +000020static const GrGLuint GR_MAX_GLUINT = ~0;
21static const GrGLint GR_INVAL_GLINT = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000022
bsalomon@google.com316f99232011-01-13 21:28:12 +000023// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000024// mucking with the state of any of the stages.
bsalomon@google.com316f99232011-01-13 21:28:12 +000025static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000026
reed@google.comac10a2d2010-12-22 21:39:39 +000027#define SKIP_CACHE_CHECK true
28
twiz@google.com0f31ca72011-03-18 17:38:11 +000029static const GrGLenum gXfermodeCoeff2Blend[] = {
30 GR_GL_ZERO,
31 GR_GL_ONE,
32 GR_GL_SRC_COLOR,
33 GR_GL_ONE_MINUS_SRC_COLOR,
34 GR_GL_DST_COLOR,
35 GR_GL_ONE_MINUS_DST_COLOR,
36 GR_GL_SRC_ALPHA,
37 GR_GL_ONE_MINUS_SRC_ALPHA,
38 GR_GL_DST_ALPHA,
39 GR_GL_ONE_MINUS_DST_ALPHA,
40 GR_GL_CONSTANT_COLOR,
41 GR_GL_ONE_MINUS_CONSTANT_COLOR,
42 GR_GL_CONSTANT_ALPHA,
43 GR_GL_ONE_MINUS_CONSTANT_ALPHA,
reed@google.comac10a2d2010-12-22 21:39:39 +000044};
45
bsalomon@google.com080773c2011-03-15 19:09:25 +000046bool GrGpuGL::BlendCoefReferencesConstant(GrBlendCoeff coeff) {
47 static const bool gCoeffReferencesBlendConst[] = {
48 false,
49 false,
50 false,
51 false,
52 false,
53 false,
54 false,
55 false,
56 false,
57 false,
58 true,
59 true,
60 true,
61 true,
62 };
63 return gCoeffReferencesBlendConst[coeff];
64 GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
65}
66
67GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
68GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
69GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
70GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
71GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
72GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
73GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
74GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
75GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
76GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
77GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
78GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
79GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
80GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
81
82GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
83
reed@google.comac10a2d2010-12-22 21:39:39 +000084///////////////////////////////////////////////////////////////////////////////
85
bsalomon@google.comd302f142011-03-03 13:54:13 +000086void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
87 GrSamplerState::SampleMode mode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000088 GrMatrix* matrix) {
89 GrAssert(NULL != texture);
90 GrAssert(NULL != matrix);
91 if (GR_Scalar1 != texture->contentScaleX() ||
92 GR_Scalar1 != texture->contentScaleY()) {
93 if (GrSamplerState::kRadial_SampleMode == mode) {
94 GrMatrix scale;
95 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
96 matrix->postConcat(scale);
97 } else if (GrSamplerState::kNormal_SampleMode == mode) {
98 GrMatrix scale;
99 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
100 matrix->postConcat(scale);
101 } else {
102 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
103 }
104 }
105 GrGLTexture::Orientation orientation = texture->orientation();
106 if (GrGLTexture::kBottomUp_Orientation == orientation) {
107 GrMatrix invY;
108 invY.setAll(GR_Scalar1, 0, 0,
109 0, -GR_Scalar1, GR_Scalar1,
110 0, 0, GrMatrix::I()[8]);
111 matrix->postConcat(invY);
112 } else {
113 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
114 }
115}
116
bsalomon@google.comd302f142011-03-03 13:54:13 +0000117bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000118 const GrSamplerState& sampler) {
119 GrAssert(NULL != texture);
120 if (!sampler.getMatrix().isIdentity()) {
121 return false;
122 }
123 if (GR_Scalar1 != texture->contentScaleX() ||
124 GR_Scalar1 != texture->contentScaleY()) {
125 return false;
126 }
127 GrGLTexture::Orientation orientation = texture->orientation();
128 if (GrGLTexture::kBottomUp_Orientation == orientation) {
129 return false;
130 } else {
131 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
132 }
133 return true;
134}
135
136///////////////////////////////////////////////////////////////////////////////
137
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000138static bool gPrintStartupSpew;
139
twiz@google.com59a190b2011-03-14 21:23:01 +0000140static bool fbo_test(int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000141
twiz@google.com0f31ca72011-03-18 17:38:11 +0000142 GrGLint savedFBO;
143 GrGLint savedTexUnit;
144 GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000145 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000146
twiz@google.com0f31ca72011-03-18 17:38:11 +0000147 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000148
twiz@google.com0f31ca72011-03-18 17:38:11 +0000149 GrGLuint testFBO;
twiz@google.com59a190b2011-03-14 21:23:01 +0000150 GR_GL(GenFramebuffers(1, &testFBO));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000151 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000152 GrGLuint testRTTex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 GR_GL(GenTextures(1, &testRTTex));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000154 GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000155 // some implementations require texture to be mip-map complete before
156 // FBO with level 0 bound as color attachment will be framebuffer complete.
twiz@google.com0f31ca72011-03-18 17:38:11 +0000157 GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
158 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
159 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
160 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000161 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000162 GR_GL_TEXTURE_2D, testRTTex, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000163 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000164 GR_GL(DeleteFramebuffers(1, &testFBO));
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000166
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000167 GR_GL(ActiveTexture(savedTexUnit));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000168 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000169
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000170 return status == GR_GL_FRAMEBUFFER_COMPLETE;
reed@google.comac10a2d2010-12-22 21:39:39 +0000171}
172
reed@google.comac10a2d2010-12-22 21:39:39 +0000173GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000174
reed@google.comeeeb5a02010-12-23 15:12:59 +0000175 if (gPrintStartupSpew) {
176 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
177 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000178 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000179 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000180 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000181 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000182 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000183 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000184 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000185 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000186 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000187
188 GrGLClearErr();
189
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000190 resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000191
twiz@google.com0f31ca72011-03-18 17:38:11 +0000192 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000193 // check FS and fixed-function texture unit limits
194 // we only use textures in the fragment stage currently.
195 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000196 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
197 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
198 GrAssert(maxTextureUnits > kNumStages);
199 }
200 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
201 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
202 GrAssert(maxTextureUnits > kNumStages);
203 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000204
reed@google.comac10a2d2010-12-22 21:39:39 +0000205 ////////////////////////////////////////////////////////////////////////////
206 // Check for supported features.
207
208 int major, minor;
209 gl_version(&major, &minor);
210
twiz@google.com0f31ca72011-03-18 17:38:11 +0000211 GrGLint numFormats;
212 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
213 GrAutoSTMalloc<10, GrGLint> formats(numFormats);
214 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000216 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000217 f8bitPaletteSupport = true;
218 break;
219 }
220 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000221
222 if (gPrintStartupSpew) {
223 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
224 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000225
226 GR_STATIC_ASSERT(0 == kNone_AALevel);
227 GR_STATIC_ASSERT(1 == kLow_AALevel);
228 GR_STATIC_ASSERT(2 == kMed_AALevel);
229 GR_STATIC_ASSERT(3 == kHigh_AALevel);
230
231 memset(fAASamples, 0, sizeof(fAASamples));
232 fMSFBOType = kNone_MSFBO;
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000233 if (GR_GL_SUPPORT_ES) {
234 if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000235 // chrome's extension is equivalent to the EXT msaa
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000236 // and fbo_blit extensions.
237 fMSFBOType = kDesktopEXT_MSFBO;
238 } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
239 fMSFBOType = kAppleES_MSFBO;
240 }
241 } else {
242 GrAssert(GR_GL_SUPPORT_DESKTOP);
243 if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
244 fMSFBOType = kDesktopARB_MSFBO;
245 } else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
246 has_gl_extension("GL_EXT_framebuffer_blit")) {
247 fMSFBOType = kDesktopEXT_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000248 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000249 }
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000250 if (gPrintStartupSpew) {
251 switch (fMSFBOType) {
252 case kNone_MSFBO:
253 GrPrintf("MSAA Support: NONE\n");
254 break;
255 case kDesktopARB_MSFBO:
256 GrPrintf("MSAA Support: DESKTOP ARB.\n");
257 break;
258 case kDesktopEXT_MSFBO:
259 GrPrintf("MSAA Support: DESKTOP EXT.\n");
260 break;
261 case kAppleES_MSFBO:
262 GrPrintf("MSAA Support: APPLE ES.\n");
263 break;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000264 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000265 }
266
267 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000268 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000269 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000270 if (maxSamples > 1 ) {
271 fAASamples[kNone_AALevel] = 0;
272 fAASamples[kLow_AALevel] = GrMax(2,
273 GrFixedFloorToInt((GR_FixedHalf) *
274 maxSamples));
275 fAASamples[kMed_AALevel] = GrMax(2,
276 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
277 maxSamples));
278 fAASamples[kHigh_AALevel] = maxSamples;
279 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000280 if (gPrintStartupSpew) {
281 GrPrintf("\tMax Samples: %d\n", maxSamples);
282 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000283 }
284
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000285 if (GR_GL_SUPPORT_DESKTOP) {
286 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
287 has_gl_extension("GL_EXT_stencil_wrap");
288 } else {
289 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
290 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000291 if (gPrintStartupSpew) {
292 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
293 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000294
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000295 if (GR_GL_SUPPORT_DESKTOP) {
296 // we could also look for GL_ATI_separate_stencil extension or
297 // GL_EXT_stencil_two_side but they use different function signatures
298 // than GL2.0+ (and than each other).
299 fTwoSidedStencilSupport = (major >= 2);
300 // supported on GL 1.4 and higher or by extension
301 fStencilWrapOpsSupport = (major > 1) ||
302 ((1 == major) && (minor >= 4)) ||
303 has_gl_extension("GL_EXT_stencil_wrap");
304 } else {
305 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
306 // an ES1 extension.
307 fTwoSidedStencilSupport = (major >= 2);
308 // stencil wrap support is in ES2, ES1 requires extension.
309 fStencilWrapOpsSupport = (major > 1) ||
310 has_gl_extension("GL_OES_stencil_wrap");
311 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000312 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000313 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
314 (fTwoSidedStencilSupport ? "YES" : "NO"),
315 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000316 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000317
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000318 if (GR_GL_SUPPORT_DESKTOP) {
319 fRGBA8Renderbuffer = true;
320 } else {
321 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
322 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000323 if (gPrintStartupSpew) {
324 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
325 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000326
327
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000328 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000329 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000330 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
331 }
332 }
333
334 if (GR_GL_SUPPORT_DESKTOP) {
335 fBufferLockSupport = true; // we require VBO support and the desktop VBO
336 // extension includes glMapBuffer.
337 } else {
338 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
339 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000340
reed@google.comeeeb5a02010-12-23 15:12:59 +0000341 if (gPrintStartupSpew) {
342 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
343 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000344
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000345 if (GR_GL_SUPPORT_DESKTOP) {
346 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
347 fNPOTTextureTileSupport = true;
348 fNPOTTextureSupport = true;
349 } else {
350 fNPOTTextureTileSupport = false;
351 fNPOTTextureSupport = false;
352 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000353 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000354 if (major >= 2) {
355 fNPOTTextureSupport = true;
356 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
357 } else {
358 fNPOTTextureSupport =
359 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
360 fNPOTTextureTileSupport = false;
361 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000362 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000363
reed@google.comac10a2d2010-12-22 21:39:39 +0000364 ////////////////////////////////////////////////////////////////////////////
365 // Experiments to determine limitations that can't be queried. TODO: Make
366 // these a preprocess that generate some compile time constants.
367
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000368 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000369
twiz@google.com59a190b2011-03-14 21:23:01 +0000370 bool simpleFBOSuccess = fbo_test(128, 128);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000371 if (gPrintStartupSpew) {
372 if (!simpleFBOSuccess) {
373 GrPrintf("FBO Sanity Test: FAILED\n");
374 } else {
375 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000376 }
377 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000378 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000379
reed@google.comac10a2d2010-12-22 21:39:39 +0000380 /* Experimentation has found that some GLs that support NPOT textures
381 do not support FBOs with a NPOT texture. They report "unsupported" FBO
382 status. I don't know how to explicitly query for this. Do an
383 experiment. Note they may support NPOT with a renderbuffer but not a
384 texture. Presumably, the implementation bloats the renderbuffer
385 internally to the next POT.
386 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000387 bool fNPOTRenderTargetSupport = false;
388 if (fNPOTTextureSupport) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000389 fNPOTRenderTargetSupport = fbo_test(200, 200);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000390 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000391
bsalomon@google.com0748f212011-02-01 22:56:16 +0000392 if (gPrintStartupSpew) {
393 if (fNPOTTextureSupport) {
394 GrPrintf("NPOT textures supported\n");
395 if (fNPOTTextureTileSupport) {
396 GrPrintf("NPOT texture tiling supported\n");
397 } else {
398 GrPrintf("NPOT texture tiling NOT supported\n");
399 }
400 if (fNPOTRenderTargetSupport) {
401 GrPrintf("NPOT render targets supported\n");
402 } else {
403 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000404 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000405 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000406 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000407 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000408 }
409
reed@google.comac10a2d2010-12-22 21:39:39 +0000410 /* The iPhone 4 has a restriction that for an FBO with texture color
411 attachment with height <= 8 then the width must be <= height. Here
412 we look for such a limitation.
413 */
414 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000415 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000416 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000417
reed@google.comeeeb5a02010-12-23 15:12:59 +0000418 if (gPrintStartupSpew) {
419 GrPrintf("Small height FBO texture experiments\n");
420 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000421
twiz@google.com0f31ca72011-03-18 17:38:11 +0000422 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
423 GrGLuint w = maxRenderSize;
424 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000425 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000426 if (gPrintStartupSpew) {
427 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
428 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000429 fMinRenderTargetHeight = i;
430 break;
431 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000432 if (gPrintStartupSpew) {
433 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
434 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000435 }
436 }
437 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
438
reed@google.comeeeb5a02010-12-23 15:12:59 +0000439 if (gPrintStartupSpew) {
440 GrPrintf("Small width FBO texture experiments\n");
441 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000442 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000443 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
444 GrGLuint w = i;
445 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000446 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000447 if (gPrintStartupSpew) {
448 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
449 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000450 fMinRenderTargetWidth = i;
451 break;
452 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000453 if (gPrintStartupSpew) {
454 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
455 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000456 }
457 }
458 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
459
twiz@google.com0f31ca72011-03-18 17:38:11 +0000460 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000461}
462
463GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000464}
465
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000466void GrGpuGL::resetContext() {
467 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000468 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000469 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000470
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000471 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000472 GR_GL(Disable(GR_GL_DEPTH_TEST));
473 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000474
twiz@google.com0f31ca72011-03-18 17:38:11 +0000475 GR_GL(Disable(GR_GL_CULL_FACE));
476 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000477 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000478
twiz@google.com0f31ca72011-03-18 17:38:11 +0000479 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000480 if (GR_GL_SUPPORT_DESKTOP) {
481 GR_GL(Disable(GR_GL_LINE_SMOOTH));
482 GR_GL(Disable(GR_GL_POINT_SMOOTH));
483 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000484 fHWAAState.fMSAAEnabled = false;
485 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000486 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000487
twiz@google.com0f31ca72011-03-18 17:38:11 +0000488 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000489 fHWDrawState.fFlagBits = 0;
490
reed@google.comac10a2d2010-12-22 21:39:39 +0000491 // we only ever use lines in hairline mode
492 GR_GL(LineWidth(1));
493
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000494 // invalid
495 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000496
reed@google.comac10a2d2010-12-22 21:39:39 +0000497 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000498 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
499 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000500
501 fHWDrawState.fBlendConstant = 0x00000000;
502 GR_GL(BlendColor(0,0,0,0));
503
reed@google.comac10a2d2010-12-22 21:39:39 +0000504 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000505
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000506 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000507
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000508 for (int s = 0; s < kNumStages; ++s) {
509 fHWDrawState.fTextures[s] = NULL;
510 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
511 -GR_ScalarMax,
512 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000513
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000514 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000515 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000516
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000517 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000518 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000519 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000520 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000521
bsalomon@google.comd302f142011-03-03 13:54:13 +0000522 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000523 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000524 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000525
526 fHWGeometryState.fIndexBuffer = NULL;
527 fHWGeometryState.fVertexBuffer = NULL;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000528 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
529 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000530 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000531
twiz@google.com0f31ca72011-03-18 17:38:11 +0000532 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000533 fHWDrawState.fRenderTarget = NULL;
534}
535
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000536GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
537
538 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
539 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
540 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
541 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
542
543 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
544 if (isRenderTarget) {
545 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
546 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
547 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
548 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
549 } else {
550 GrAssert(!isTexture); // this should have been filtered by GrContext
551 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
552 }
553 } else {
554 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
555 }
556 // we don't know what the RB ids are without glGets and we don't care
557 // since we aren't responsible for deleting them.
558 rtIDs.fStencilRenderbufferID = 0;
559 rtIDs.fMSColorRenderbufferID = 0;
560
561 rtIDs.fOwnIDs = false;
562 } else {
563 rtIDs.reset();
564 }
565
566 if (isTexture) {
567 GrGLTexture::GLTextureDesc texDesc;
568 GrGLenum dontCare;
569 if (!canBeTexture(desc.fConfig, &dontCare,
570 &texDesc.fUploadFormat,
571 &texDesc.fUploadType)) {
572 return NULL;
573 }
574
575 GrGLTexture::TexParams params;
576
577 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
578 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
579
580 texDesc.fFormat = texDesc.fFormat;
581 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
582 texDesc.fStencilBits = desc.fStencilBits;
583 texDesc.fTextureID = desc.fPlatformTexture;
584 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
585 texDesc.fOwnsID = false;
586
587 params.invalidate(); // rather than do glGets.
588
589 return new GrGLTexture(this, texDesc, rtIDs, params);
590 } else {
591 GrGLIRect viewport;
592 viewport.fLeft = 0;
593 viewport.fBottom = 0;
594 viewport.fWidth = desc.fWidth;
595 viewport.fHeight = desc.fHeight;
596
597 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
598 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
599 viewport, NULL);
600 }
601}
602
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000603GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
reed@google.comac10a2d2010-12-22 21:39:39 +0000604 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000605 int stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000606 bool isMultisampled,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000607 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000608 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000609 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
610 rtIDs.fStencilRenderbufferID = 0;
611 rtIDs.fMSColorRenderbufferID = 0;
612 rtIDs.fTexFBOID = 0;
613 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000614 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000615
616 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000617 viewport.fLeft = 0;
618 viewport.fBottom = 0;
619 viewport.fWidth = width;
620 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000621
twiz@google.com0f31ca72011-03-18 17:38:11 +0000622 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
623 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000624
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000625 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
626 isMultisampled, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000627}
628
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000629GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000630
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000631 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000632
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000633 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000634 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
635 rtIDs.fMSColorRenderbufferID = 0;
636 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000637
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000638 GrGLIRect viewport;
639 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000640 GrGLuint stencilBits;
641 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000642
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000643 GrGLint samples;
644 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
645
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000646 rtIDs.fOwnIDs = false;
647
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000648 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
649 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000650}
651
bsalomon@google.com5782d712011-01-21 21:03:59 +0000652///////////////////////////////////////////////////////////////////////////////
653
twiz@google.com0f31ca72011-03-18 17:38:11 +0000654static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000655
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000656struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000657 GrGLenum fEnum;
658 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000659 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000660};
661
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000662const StencilFormat* GrGLStencilFormats() {
663 // defines stencil formats from more to less preferred
664 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000665 {GR_GL_STENCIL_INDEX8, 8, false},
666 {GR_GL_STENCIL_INDEX16, 16, false},
667 {GR_GL_DEPTH24_STENCIL8, 8, true },
668 {GR_GL_STENCIL_INDEX4, 4, false},
669 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
670 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
671 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000672 };
673
674 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000675 {GR_GL_STENCIL_INDEX8, 8, false},
676 {GR_GL_DEPTH24_STENCIL8, 8, true },
677 {GR_GL_STENCIL_INDEX4, 4, false},
678 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000679 };
680
681 if (GR_GL_SUPPORT_DESKTOP) {
682 return desktopStencilFormats;
683 } else {
684 return esStencilFormats;
685 }
686}
687
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000688// good to set a break-point here to know when createTexture fails
689static GrTexture* return_null_texture() {
690// GrAssert(!"null texture");
691 return NULL;
692}
693
694#if GR_DEBUG
695static size_t as_size_t(int x) {
696 return x;
697}
698#endif
699
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000700GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
701 const void* srcData,
702 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000703
704#if GR_COLLECT_STATS
705 ++fStats.fTextureCreateCnt;
706#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000707
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000708 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000709
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000710 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000711 GR_GL_NEAREST,
712 GR_GL_CLAMP_TO_EDGE,
713 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000714 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000715
reed@google.comac10a2d2010-12-22 21:39:39 +0000716 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000717 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000718
719 glDesc.fContentWidth = desc.fWidth;
720 glDesc.fContentHeight = desc.fHeight;
721 glDesc.fAllocWidth = desc.fWidth;
722 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000723 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000724 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000725 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000726
727 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
728 if (!canBeTexture(desc.fFormat,
729 &internalFormat,
730 &glDesc.fUploadFormat,
731 &glDesc.fUploadType)) {
732 return return_null_texture();
733 }
734
735 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000736 GrGLint samples = fAASamples[desc.fAALevel];
reed@google.comac10a2d2010-12-22 21:39:39 +0000737 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
738 GrPrintf("AA RT requested but not supported on this platform.");
739 }
740
741 GR_GL(GenTextures(1, &glDesc.fTextureID));
742 if (!glDesc.fTextureID) {
743 return return_null_texture();
744 }
745
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000746 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000747
reed@google.com5e762232011-04-04 18:15:49 +0000748 // in case we need a temporary, trimmed copy of the src pixels
749 GrAutoSMalloc<128 * 128> trimStorage;
750
reed@google.comac10a2d2010-12-22 21:39:39 +0000751 /*
752 * check if our srcData has extra bytes past each row. If so, we need
753 * to trim those off here, since GL doesn't let us pass the rowBytes as
754 * a parameter to glTexImage2D
755 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000756 if (GR_GL_SUPPORT_DESKTOP) {
757 if (srcData) {
758 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
759 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000760 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000761 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000762 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
763 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000764 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000765 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000766 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000767 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000768 for (uint32_t y = 0; y < desc.fHeight; y++) {
769 memcpy(dst, src, trimRowBytes);
770 src += rowBytes;
771 dst += trimRowBytes;
772 }
773 // now point srcData to our trimmed version
774 srcData = trimStorage.get();
775 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000776 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000777
reed@google.comac10a2d2010-12-22 21:39:39 +0000778 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000779 if (!this->npotRenderTargetSupport()) {
780 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
781 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
782 }
783
reed@google.comac10a2d2010-12-22 21:39:39 +0000784 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
785 glDesc.fAllocWidth);
786 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
787 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000788 } else if (!this->npotTextureSupport()) {
789 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
790 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000791 }
792
twiz@google.com0f31ca72011-03-18 17:38:11 +0000793 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
794 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
795 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000796 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000797 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
798 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000799 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000800 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
801 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000802 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000803 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
804 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000805 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000806
twiz@google.com0f31ca72011-03-18 17:38:11 +0000807 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000808 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000809 supports8BitPalette()) {
810 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
811 GrAssert(desc.fWidth == glDesc.fAllocWidth);
812 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000813 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
814 kColorTableSize;
815 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000816 glDesc.fAllocWidth, glDesc.fAllocHeight,
817 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000818 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000819 } else {
820 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
821 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000822 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000823 glDesc.fAllocWidth, glDesc.fAllocHeight,
824 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000825 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000826 desc.fHeight, glDesc.fUploadFormat,
827 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000828 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000829
830 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
831 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
832 uint32_t maxTexels = extraW * extraH;
833 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
834 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
835
836 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
837
838 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
839 if (extraH) {
840 uint8_t* lastRowStart = (uint8_t*) srcData +
841 (desc.fHeight - 1) * rowSize;
842 uint8_t* extraRowStart = (uint8_t*)texels.get();
843
844 for (uint32_t i = 0; i < extraH; ++i) {
845 memcpy(extraRowStart, lastRowStart, rowSize);
846 extraRowStart += rowSize;
847 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000848 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000849 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
850 texels.get()));
851 }
852 if (extraW) {
853 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
854 uint8_t* extraTexel = (uint8_t*)texels.get();
855 for (uint32_t j = 0; j < desc.fHeight; ++j) {
856 for (uint32_t i = 0; i < extraW; ++i) {
857 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
858 extraTexel += glDesc.fUploadByteCount;
859 }
860 edgeTexel += rowSize;
861 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000862 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000863 desc.fHeight, glDesc.fUploadFormat,
864 glDesc.fUploadType, texels.get()));
865 }
866 if (extraW && extraH) {
867 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
868 - glDesc.fUploadByteCount;
869 uint8_t* extraTexel = (uint8_t*)texels.get();
870 for (uint32_t i = 0; i < extraW*extraH; ++i) {
871 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
872 extraTexel += glDesc.fUploadByteCount;
873 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000874 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000875 extraW, extraH, glDesc.fUploadFormat,
876 glDesc.fUploadType, texels.get()));
877 }
878
879 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000880 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000881 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
882 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000883 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000884 }
885 }
886
887 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
888
889 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
890 rtIDs.fStencilRenderbufferID = 0;
891 rtIDs.fMSColorRenderbufferID = 0;
892 rtIDs.fRTFBOID = 0;
893 rtIDs.fTexFBOID = 0;
894 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000895 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000896
897 if (renderTarget) {
898#if GR_COLLECT_STATS
899 ++fStats.fRenderTargetCreateCnt;
900#endif
901 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000902 GrGLenum status;
903 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000904
905 // If need have both RT flag and srcData we have
906 // to invert the data before uploading because FBO
907 // will be rendered bottom up
908 GrAssert(NULL == srcData);
909 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
910
twiz@google.com59a190b2011-03-14 21:23:01 +0000911 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000912 GrAssert(rtIDs.fTexFBOID);
913
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000914 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000915 // to one and then resolve to the texture bound to the other.
916 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000917 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000918 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000919 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000920 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
921 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000922 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000923 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000924 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
925 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000926 return return_null_texture();
927 }
928 } else {
929 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
930 }
bsalomon@google.comf6a7c112011-03-24 16:14:10 +0000931 if (!(kNoStencil_TextureFlag & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000932 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000933 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000934 }
935
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000936 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000937 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000938 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000939 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000940
twiz@google.com0f31ca72011-03-18 17:38:11 +0000941 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000942
943 const StencilFormat* stencilFormats = GrGLStencilFormats();
944 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000945 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000946 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000947 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000948 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000949 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000950 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000951 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000952 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000953 glDesc.fAllocWidth,
954 glDesc.fAllocHeight));
955 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000956 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000957 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000958 glDesc.fAllocWidth,
959 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000960 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000961 err = GrGLGetGLInterface()->fGetError();
962 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000963 continue;
964 }
965 }
966 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
967 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000968 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000969 rtIDs.fMSColorRenderbufferID));
970 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000971 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000972 samples,
973 msColorRenderbufferFormat,
974 glDesc.fAllocWidth,
975 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000976 err = GrGLGetGLInterface()->fGetError();
977 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000978 continue;
979 }
980 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000981 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000982
983#if GR_COLLECT_STATS
984 ++fStats.fRenderTargetChngCnt;
985#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000986 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
987 GR_GL_COLOR_ATTACHMENT0,
988 GR_GL_TEXTURE_2D,
989 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000990 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000991 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
992 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000993 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
994 status, desc.fWidth, desc.fHeight);
995 continue;
996 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000997 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000998 #if GR_COLLECT_STATS
999 ++fStats.fRenderTargetChngCnt;
1000 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001001 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1002 GR_GL_COLOR_ATTACHMENT0,
1003 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001004 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001005
1006 }
1007 if (rtIDs.fStencilRenderbufferID) {
1008 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001009 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1010 GR_GL_STENCIL_ATTACHMENT,
1011 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001012 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001013 // if it is a packed format bind to depth also, otherwise
1014 // we may get an unsupported fbo completeness result
1015 if (stencilFormats[i].fPacked) {
1016 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1017 GR_GL_DEPTH_ATTACHMENT,
1018 GR_GL_RENDERBUFFER,
1019 rtIDs.fStencilRenderbufferID));
1020 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001021 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001022 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001023
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001024 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001025 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1026 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001027 // undo the depth bind
1028 if (rtIDs.fStencilRenderbufferID &&
1029 stencilFormats[i].fPacked) {
1030 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1031 GR_GL_DEPTH_ATTACHMENT,
1032 GR_GL_RENDERBUFFER,
1033 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001034 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001035 continue;
1036 }
1037 // we're successful!
1038 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001039 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001040 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001041 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001042 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001043 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001044 }
1045 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001046 break;
1047 }
1048 if (failed) {
1049 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001050 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001051 }
1052 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001053 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001054 }
1055 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001056 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001057 }
1058 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001059 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001060 }
1061 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1062 return return_null_texture();
1063 }
1064 }
1065#ifdef TRACE_TEXTURE_CREATION
1066 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1067 tex->fTextureID, width, height, tex->fUploadByteCount);
1068#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001069 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001070
1071 if (0 != rtIDs.fTexFBOID) {
1072 GrRenderTarget* rt = tex->asRenderTarget();
1073 // We've messed with FBO state but may not have set the correct viewport
1074 // so just dirty the rendertarget state to force a resend.
1075 fHWDrawState.fRenderTarget = NULL;
1076
1077 // clear the new stencil buffer if we have one
bsalomon@google.comf6a7c112011-03-24 16:14:10 +00001078 if (!(desc.fFlags & kNoStencil_TextureFlag)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001079 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1080 fCurrDrawState.fRenderTarget = rt;
1081 eraseStencil(0, ~0);
1082 fCurrDrawState.fRenderTarget = rtSave;
1083 }
1084 }
1085 return tex;
1086}
1087
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001088GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001089 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001090 GR_GL(GenBuffers(1, &id));
1091 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001092 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001093 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 GrGLClearErr();
1095 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001096 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1097 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1098 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001099 GR_GL(DeleteBuffers(1, &id));
1100 // deleting bound buffer does implicit bind to 0
1101 fHWGeometryState.fVertexBuffer = NULL;
1102 return NULL;
1103 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001104 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001105 size, dynamic);
1106 fHWGeometryState.fVertexBuffer = vertexBuffer;
1107 return vertexBuffer;
1108 }
1109 return NULL;
1110}
1111
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001112GrIndexBuffer* GrGpuGL::createIndexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001113 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001114 GR_GL(GenBuffers(1, &id));
1115 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001116 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001117 GrGLClearErr();
1118 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001119 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1120 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1121 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001122 GR_GL(DeleteBuffers(1, &id));
1123 // deleting bound buffer does implicit bind to 0
1124 fHWGeometryState.fIndexBuffer = NULL;
1125 return NULL;
1126 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001127 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001128 size, dynamic);
1129 fHWGeometryState.fIndexBuffer = indexBuffer;
1130 return indexBuffer;
1131 }
1132 return NULL;
1133}
1134
reed@google.comac10a2d2010-12-22 21:39:39 +00001135void GrGpuGL::flushScissor(const GrIRect* rect) {
1136 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001137 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001138 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001139
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001140 GrGLIRect scissor;
1141 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001142 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001143 rect->width(), rect->height());
1144 if (scissor.contains(vp)) {
1145 rect = NULL;
1146 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001147 }
1148
1149 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001150 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001151 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001152 fHWBounds.fScissorRect = scissor;
1153 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001154 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001155 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 fHWBounds.fScissorEnabled = true;
1157 }
1158 } else {
1159 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001160 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001161 fHWBounds.fScissorEnabled = false;
1162 }
1163 }
1164}
1165
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001166void GrGpuGL::eraseColorHelper(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001167 if (NULL == fCurrDrawState.fRenderTarget) {
1168 return;
1169 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001170 flushRenderTarget();
1171 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001172 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001173 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001174 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001175 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001176 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001177 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1178 GrColorUnpackG(color)/255.f,
1179 GrColorUnpackB(color)/255.f,
1180 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001181 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001182}
1183
1184void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001185 if (NULL == fCurrDrawState.fRenderTarget) {
1186 return;
1187 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001188 flushRenderTarget();
1189 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001190 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001191 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001192 }
1193 GR_GL(StencilMask(mask));
1194 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001195 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001196 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001197}
1198
bsalomon@google.comd302f142011-03-03 13:54:13 +00001199void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001200 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001201#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001202 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001203 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001204 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001205#else
1206 // we could just clear the clip bit but when we go through
1207 // angle a partial stencil mask will cause clears to be
1208 // turned into draws. Our contract on GrDrawTarget says that
1209 // changing the clip between stencil passes may or may not
1210 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001211 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001212#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001213 flushRenderTarget();
1214 flushScissor(&rect);
1215 GR_GL(StencilMask(clipStencilMask));
1216 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001217 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001218 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001219}
1220
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001221void GrGpuGL::forceRenderTargetFlushHelper() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001222 flushRenderTarget();
1223}
1224
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001225bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1226 int left, int top, int width, int height,
1227 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001228 GrGLenum internalFormat; // we don't use this for glReadPixels
1229 GrGLenum format;
1230 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001231 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1232 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001233 }
1234 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1235 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1236 switch (tgt->getResolveType()) {
1237 case GrGLRenderTarget::kCantResolve_ResolveType:
1238 return false;
1239 case GrGLRenderTarget::kAutoResolves_ResolveType:
1240 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1241 fCurrDrawState.fRenderTarget = target;
1242 flushRenderTarget();
1243 break;
1244 case GrGLRenderTarget::kCanResolve_ResolveType:
1245 resolveRenderTarget(tgt);
1246 // we don't track the state of the READ FBO ID.
1247 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1248 break;
1249 default:
1250 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001251 }
1252
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001253 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001254
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001255 // the read rect is viewport-relative
1256 GrGLIRect readRect;
1257 readRect.setRelativeTo(glvp, left, top, width, height);
1258 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001259 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001260 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001261
1262 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1263 // API presents top-to-bottom
1264 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001265 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001266 GrAutoMalloc rowStorage(stride);
1267 void* tmp = rowStorage.get();
1268
1269 const int halfY = height >> 1;
1270 char* top = reinterpret_cast<char*>(buffer);
1271 char* bottom = top + (height - 1) * stride;
1272 for (int y = 0; y < halfY; y++) {
1273 memcpy(tmp, top, stride);
1274 memcpy(top, bottom, stride);
1275 memcpy(bottom, tmp, stride);
1276 top += stride;
1277 bottom -= stride;
1278 }
1279 }
1280 return true;
1281}
1282
1283void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001284
1285 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1286
reed@google.comac10a2d2010-12-22 21:39:39 +00001287 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1288 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001289 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001290 #if GR_COLLECT_STATS
1291 ++fStats.fRenderTargetChngCnt;
1292 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001293 rt->flagAsNeedingResolve();
reed@google.comac10a2d2010-12-22 21:39:39 +00001294 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001295 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1296 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001297 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1298 }
1299 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001300 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001301 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001302 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001303 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001304 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001305 fHWBounds.fViewportRect = vp;
1306 }
1307 }
1308}
1309
twiz@google.com0f31ca72011-03-18 17:38:11 +00001310GrGLenum gPrimitiveType2GLMode[] = {
1311 GR_GL_TRIANGLES,
1312 GR_GL_TRIANGLE_STRIP,
1313 GR_GL_TRIANGLE_FAN,
1314 GR_GL_POINTS,
1315 GR_GL_LINES,
1316 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001317};
1318
bsalomon@google.comd302f142011-03-03 13:54:13 +00001319#define SWAP_PER_DRAW 0
1320
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001321#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001322 #if GR_MAC_BUILD
1323 #include <AGL/agl.h>
1324 #elif GR_WIN32_BUILD
1325 void SwapBuf() {
1326 DWORD procID = GetCurrentProcessId();
1327 HWND hwnd = GetTopWindow(GetDesktopWindow());
1328 while(hwnd) {
1329 DWORD wndProcID = 0;
1330 GetWindowThreadProcessId(hwnd, &wndProcID);
1331 if(wndProcID == procID) {
1332 SwapBuffers(GetDC(hwnd));
1333 }
1334 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1335 }
1336 }
1337 #endif
1338#endif
1339
bsalomon@google.comffca4002011-02-22 20:34:01 +00001340void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001341 uint32_t startVertex,
1342 uint32_t startIndex,
1343 uint32_t vertexCount,
1344 uint32_t indexCount) {
1345 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1346
twiz@google.com0f31ca72011-03-18 17:38:11 +00001347 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001348
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001349 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1350 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1351
1352 // our setupGeometry better have adjusted this to zero since
1353 // DrawElements always draws from the begining of the arrays for idx 0.
1354 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001355
1356 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001357 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001358#if SWAP_PER_DRAW
1359 glFlush();
1360 #if GR_MAC_BUILD
1361 aglSwapBuffers(aglGetCurrentContext());
1362 int set_a_break_pt_here = 9;
1363 aglSwapBuffers(aglGetCurrentContext());
1364 #elif GR_WIN32_BUILD
1365 SwapBuf();
1366 int set_a_break_pt_here = 9;
1367 SwapBuf();
1368 #endif
1369#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001370}
1371
bsalomon@google.comffca4002011-02-22 20:34:01 +00001372void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001373 uint32_t startVertex,
1374 uint32_t vertexCount) {
1375 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1376
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001377 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1378
1379 // our setupGeometry better have adjusted this to zero.
1380 // DrawElements doesn't take an offset so we always adjus the startVertex.
1381 GrAssert(0 == startVertex);
1382
1383 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1384 // account for startVertex in the DrawElements case. So we always
1385 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001386 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001387#if SWAP_PER_DRAW
1388 glFlush();
1389 #if GR_MAC_BUILD
1390 aglSwapBuffers(aglGetCurrentContext());
1391 int set_a_break_pt_here = 9;
1392 aglSwapBuffers(aglGetCurrentContext());
1393 #elif GR_WIN32_BUILD
1394 SwapBuf();
1395 int set_a_break_pt_here = 9;
1396 SwapBuf();
1397 #endif
1398#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001399}
1400
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001401void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001402
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001403 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001404 GrAssert(kNone_MSFBO != fMSFBOType);
1405 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001406 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001407 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001408 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001409 rt->textureFBOID()));
1410 #if GR_COLLECT_STATS
1411 ++fStats.fRenderTargetChngCnt;
1412 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001413 // make sure we go through flushRenderTarget() since we've modified
1414 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001415 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001416 const GrGLIRect& vp = rt->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001417
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001418 if (kAppleES_MSFBO == fMSFBOType) {
1419 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001420 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001421 GR_GL(Scissor(vp.fLeft, vp.fBottom,
1422 vp.fWidth, vp.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001423 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001424 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001425 fHWBounds.fScissorEnabled = true;
1426 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001427 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001428 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001429 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1430 flushScissor(NULL);
1431 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001432 int right = vp.fLeft + vp.fWidth;
1433 int top = vp.fBottom + vp.fHeight;
1434 GR_GL(BlitFramebuffer(vp.fLeft, vp.fBottom, right, top,
1435 vp.fLeft, vp.fBottom, right, top,
1436 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001437 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001438 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001439 }
1440}
1441
twiz@google.com0f31ca72011-03-18 17:38:11 +00001442static const GrGLenum grToGLStencilFunc[] = {
1443 GR_GL_ALWAYS, // kAlways_StencilFunc
1444 GR_GL_NEVER, // kNever_StencilFunc
1445 GR_GL_GREATER, // kGreater_StencilFunc
1446 GR_GL_GEQUAL, // kGEqual_StencilFunc
1447 GR_GL_LESS, // kLess_StencilFunc
1448 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1449 GR_GL_EQUAL, // kEqual_StencilFunc,
1450 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001451};
1452GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1453GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1454GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1455GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1456GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1457GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1458GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1459GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1460GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1461
twiz@google.com0f31ca72011-03-18 17:38:11 +00001462static const GrGLenum grToGLStencilOp[] = {
1463 GR_GL_KEEP, // kKeep_StencilOp
1464 GR_GL_REPLACE, // kReplace_StencilOp
1465 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1466 GR_GL_INCR, // kIncClamp_StencilOp
1467 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1468 GR_GL_DECR, // kDecClamp_StencilOp
1469 GR_GL_ZERO, // kZero_StencilOp
1470 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001471};
1472GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1473GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1474GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1475GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1476GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1477GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1478GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1479GR_STATIC_ASSERT(6 == kZero_StencilOp);
1480GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1481
reed@google.comac10a2d2010-12-22 21:39:39 +00001482void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001483 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001484
1485 // use stencil for clipping if clipping is enabled and the clip
1486 // has been written into the stencil.
1487 bool stencilClip = fClipState.fClipInStencil &&
1488 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001489 bool stencilChange = fHWStencilClip != stencilClip ||
1490 fHWDrawState.fStencilSettings != *settings ||
1491 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1492 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001493
1494 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001495
bsalomon@google.comd302f142011-03-03 13:54:13 +00001496 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1497 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001498
bsalomon@google.comd302f142011-03-03 13:54:13 +00001499 if (settings->isDisabled()) {
1500 if (stencilClip) {
1501 settings = &gClipStencilSettings;
1502 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001503 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001504
1505 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001506 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001507 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001508 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001509 #if GR_DEBUG
1510 if (!fStencilWrapOpsSupport) {
1511 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1512 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1513 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1514 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1515 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1516 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1517 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1518 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1519 }
1520 #endif
1521 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1522 GrAssert(stencilBits ||
1523 (GrStencilSettings::gDisabled ==
1524 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001525 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1526 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001527
1528 unsigned int frontRef = settings->fFrontFuncRef;
1529 unsigned int frontMask = settings->fFrontFuncMask;
1530 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001531 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001532
1533 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1534
1535 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1536 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1537 } else {
1538 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1539
1540 ConvertStencilFuncAndMask(settings->fFrontFunc,
1541 stencilClip,
1542 clipStencilMask,
1543 userStencilMask,
1544 &frontRef,
1545 &frontMask);
1546 frontWriteMask &= userStencilMask;
1547 }
1548 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001549 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001550 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001551 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001552 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001553 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001554 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001555 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001556 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001557 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001558
1559 unsigned int backRef = settings->fBackFuncRef;
1560 unsigned int backMask = settings->fBackFuncMask;
1561 unsigned int backWriteMask = settings->fBackWriteMask;
1562
1563
1564 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1565 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1566 backFunc = grToGLStencilFunc[settings->fBackFunc];
1567 } else {
1568 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1569 ConvertStencilFuncAndMask(settings->fBackFunc,
1570 stencilClip,
1571 clipStencilMask,
1572 userStencilMask,
1573 &backRef,
1574 &backMask);
1575 backWriteMask &= userStencilMask;
1576 }
1577
twiz@google.com0f31ca72011-03-18 17:38:11 +00001578 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1579 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1580 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1581 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1582 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001583 grToGLStencilOp[settings->fFrontPassOp],
1584 grToGLStencilOp[settings->fFrontPassOp]));
1585
twiz@google.com0f31ca72011-03-18 17:38:11 +00001586 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001587 grToGLStencilOp[settings->fBackPassOp],
1588 grToGLStencilOp[settings->fBackPassOp]));
1589 } else {
1590 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1591 GR_GL(StencilMask(frontWriteMask));
1592 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1593 grToGLStencilOp[settings->fFrontPassOp],
1594 grToGLStencilOp[settings->fFrontPassOp]));
1595 }
1596 }
1597 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001598 fHWStencilClip = stencilClip;
1599 }
1600}
1601
bsalomon@google.com0650e812011-04-08 18:07:53 +00001602bool GrGpuGL::useSmoothLines() {
1603 // there is a conflict between using smooth lines and our use of
1604 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1605 // but not in a premul-alpha way. So we only use them when our alpha
1606 // is 0xff.
1607
1608 // TODO: write a smarter line frag shader.
1609
1610 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1611 canDisableBlend();
1612}
1613
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001614void GrGpuGL::flushAAState(GrPrimitiveType type) {
1615 if (GR_GL_SUPPORT_DESKTOP) {
1616 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1617 // smooth lines.
1618
1619 // we prefer smooth lines over multisampled lines
1620 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001621 if (GrIsPrimTypeLines(type)) {
1622 bool smooth = useSmoothLines();
1623 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001624 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1625 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001626 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001627 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1628 fHWAAState.fSmoothLineEnabled = false;
1629 }
1630 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1631 fHWAAState.fMSAAEnabled) {
1632 GR_GL(Disable(GR_GL_MULTISAMPLE));
1633 fHWAAState.fMSAAEnabled = false;
1634 }
1635 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1636 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1637 fHWAAState.fMSAAEnabled) {
1638 if (fHWAAState.fMSAAEnabled) {
1639 GR_GL(Disable(GR_GL_MULTISAMPLE));
1640 fHWAAState.fMSAAEnabled = false;
1641 } else {
1642 GR_GL(Enable(GR_GL_MULTISAMPLE));
1643 fHWAAState.fMSAAEnabled = true;
1644 }
1645 }
1646 }
1647}
1648
bsalomon@google.com0650e812011-04-08 18:07:53 +00001649void GrGpuGL::flushBlend(GrPrimitiveType type) {
1650 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1651 if (fHWBlendDisabled) {
1652 GR_GL(Enable(GR_GL_BLEND));
1653 fHWBlendDisabled = false;
1654 }
1655 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1656 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1657 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1658 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1659 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1660 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1661 }
1662 } else {
1663 bool blendOff = canDisableBlend();
1664 if (fHWBlendDisabled != blendOff) {
1665 if (blendOff) {
1666 GR_GL(Disable(GR_GL_BLEND));
1667 } else {
1668 GR_GL(Enable(GR_GL_BLEND));
1669 }
1670 fHWBlendDisabled = blendOff;
1671 }
1672 if (!blendOff) {
1673 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1674 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1675 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1676 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1677 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1678 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1679 }
1680 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1681 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1682 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1683
1684 float c[] = {
1685 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1686 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1687 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1688 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1689 };
1690 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1691 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1692 }
1693 }
1694 }
1695}
1696
bsalomon@google.comffca4002011-02-22 20:34:01 +00001697bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001698
1699 // GrGpu::setupClipAndFlushState should have already checked this
1700 // and bailed if not true.
1701 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001702
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001703 for (int s = 0; s < kNumStages; ++s) {
1704 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001705
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001706 // bind texture and set sampler state
1707 if (usingTexture) {
1708 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001709
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001710 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001711 // if we created a rt/tex and rendered to it without using a
1712 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001713 // the last bound texture, but it needs resolving. So keep this
1714 // out of the "last != next" check.
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001715 GrGLRenderTarget* texRT =
1716 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1717 if (NULL != texRT) {
1718 resolveRenderTarget(texRT);
1719 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001720
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001721 if (fHWDrawState.fTextures[s] != nextTexture) {
1722 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001723 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001724 #if GR_COLLECT_STATS
1725 ++fStats.fTextureChngCnt;
1726 #endif
1727 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1728 fHWDrawState.fTextures[s] = nextTexture;
1729 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001730
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001731 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001732 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001733 nextTexture->getTexParams();
1734 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001735
twiz@google.com0f31ca72011-03-18 17:38:11 +00001736 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1737 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001738 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001739 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001740 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001741 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001742
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001743 if (newTexParams.fFilter != oldTexParams.fFilter) {
1744 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001745 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1746 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001747 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001748 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1749 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001750 newTexParams.fFilter));
1751 }
1752 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1753 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001754 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1755 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001756 newTexParams.fWrapS));
1757 }
1758 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1759 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001760 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1761 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001762 newTexParams.fWrapT));
1763 }
1764 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001765
1766 // The texture matrix has to compensate for texture width/height
1767 // and NPOT-embedded-in-POT
1768 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001769 } else {
1770 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001771 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001772 }
1773 }
1774 }
1775
1776 flushRenderTarget();
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001777 flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001778 flushBlend(type);
1779
reed@google.comac10a2d2010-12-22 21:39:39 +00001780 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1781 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1782 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001783 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001784 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001785 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001786 }
1787 }
1788
bsalomon@google.comd302f142011-03-03 13:54:13 +00001789 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1790 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001791 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001792 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001793 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001794 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001795 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001796 }
1797 GR_GL(ColorMask(mask, mask, mask, mask));
1798 }
1799
bsalomon@google.comd302f142011-03-03 13:54:13 +00001800 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1801 switch (fCurrDrawState.fDrawFace) {
1802 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001803 GR_GL(Enable(GR_GL_CULL_FACE));
1804 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001805 break;
1806 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001807 GR_GL(Enable(GR_GL_CULL_FACE));
1808 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001809 break;
1810 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001811 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001812 break;
1813 default:
1814 GrCrash("Unknown draw face.");
1815 }
1816 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1817 }
1818
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001819#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001820 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001821 for (int s = 0; s < kNumStages; ++s) {
1822 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1823 NULL == fCurrDrawState.fRenderTarget ||
1824 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001825 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001826 fCurrDrawState.fRenderTarget);
1827 }
1828#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001829
reed@google.comac10a2d2010-12-22 21:39:39 +00001830 flushStencil();
1831
bsalomon@google.comd302f142011-03-03 13:54:13 +00001832 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001833 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001834 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001835}
1836
1837void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001838 if (fHWGeometryState.fVertexBuffer != buffer) {
1839 fHWGeometryState.fArrayPtrsDirty = true;
1840 fHWGeometryState.fVertexBuffer = buffer;
1841 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001842}
1843
1844void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001845 if (fHWGeometryState.fVertexBuffer == buffer) {
1846 // deleting bound buffer does implied bind to 0
1847 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001848 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001849 }
1850}
1851
1852void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1853 fGeometrySrc.fIndexBuffer = buffer;
1854}
1855
1856void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001857 if (fHWGeometryState.fIndexBuffer == buffer) {
1858 // deleting bound buffer does implied bind to 0
1859 fHWGeometryState.fIndexBuffer = NULL;
1860 }
1861}
1862
reed@google.comac10a2d2010-12-22 21:39:39 +00001863void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1864 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001865 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001866 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001867 }
1868 if (fHWDrawState.fRenderTarget == renderTarget) {
1869 fHWDrawState.fRenderTarget = NULL;
1870 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001871}
1872
1873void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001874 for (int s = 0; s < kNumStages; ++s) {
1875 if (fCurrDrawState.fTextures[s] == texture) {
1876 fCurrDrawState.fTextures[s] = NULL;
1877 }
1878 if (fHWDrawState.fTextures[s] == texture) {
1879 // deleting bound texture does implied bind to 0
1880 fHWDrawState.fTextures[s] = NULL;
1881 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001882 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001883}
1884
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001885bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001886 GrGLenum* internalFormat,
1887 GrGLenum* format,
1888 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001889 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001890 case kRGBA_8888_GrPixelConfig:
1891 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001892 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001893 if (GR_GL_SUPPORT_ES) {
1894 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1895 // format for a BGRA is BGRA not RGBA (as on desktop)
1896 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1897 } else {
1898 *internalFormat = GR_GL_RGBA;
1899 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001900 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001901 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001902 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001903 *format = GR_GL_RGB;
1904 *internalFormat = GR_GL_RGB;
1905 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001906 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001907 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001908 *format = GR_GL_RGBA;
1909 *internalFormat = GR_GL_RGBA;
1910 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001911 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001912 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001913 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001914 *format = GR_GL_PALETTE8_RGBA8;
1915 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001916 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001917 } else {
1918 return false;
1919 }
1920 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001921 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001922 *format = GR_GL_ALPHA;
1923 *internalFormat = GR_GL_ALPHA;
1924 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001925 break;
1926 default:
1927 return false;
1928 }
1929 return true;
1930}
1931
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001932void GrGpuGL::setTextureUnit(int unit) {
1933 GrAssert(unit >= 0 && unit < kNumStages);
1934 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001935 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001936 fActiveTextureUnitIdx = unit;
1937 }
1938}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001939
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001940void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001941 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1942 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001943 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1944 }
1945}
1946
reed@google.comac10a2d2010-12-22 21:39:39 +00001947/* On ES the internalFormat and format must match for TexImage and we use
1948 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1949 decide the internalFormat. However, on ES internalFormat for
1950 RenderBufferStorage* has to be a specific format (not a base format like
1951 GL_RGBA).
1952 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001953bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001954 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001955 case kRGBA_8888_GrPixelConfig:
1956 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001957 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001958 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001959 return true;
1960 } else {
1961 return false;
1962 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001963 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001964 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1965 // with FBO extension desktop GL has
1966 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001967 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001968 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001969 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001970 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001971 return true;
1972 default:
1973 return false;
1974 }
1975}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001976
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001977void GrGpuGL::resetDirtyFlags() {
1978 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1979}
1980
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001981void GrGpuGL::setBuffers(bool indexed,
1982 int* extraVertexOffset,
1983 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001984
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001985 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001986
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001987 GrGLVertexBuffer* vbuf;
1988 switch (fGeometrySrc.fVertexSrc) {
1989 case kBuffer_GeometrySrcType:
1990 *extraVertexOffset = 0;
1991 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1992 break;
1993 case kArray_GeometrySrcType:
1994 case kReserved_GeometrySrcType:
1995 finalizeReservedVertices();
1996 *extraVertexOffset = fCurrPoolStartVertex;
1997 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1998 break;
1999 default:
2000 vbuf = NULL; // suppress warning
2001 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002002 }
2003
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002004 GrAssert(NULL != vbuf);
2005 GrAssert(!vbuf->isLocked());
2006 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002007 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002008 fHWGeometryState.fArrayPtrsDirty = true;
2009 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002010 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002011
2012 if (indexed) {
2013 GrAssert(NULL != extraIndexOffset);
2014
2015 GrGLIndexBuffer* ibuf;
2016 switch (fGeometrySrc.fIndexSrc) {
2017 case kBuffer_GeometrySrcType:
2018 *extraIndexOffset = 0;
2019 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2020 break;
2021 case kArray_GeometrySrcType:
2022 case kReserved_GeometrySrcType:
2023 finalizeReservedIndices();
2024 *extraIndexOffset = fCurrPoolStartIndex;
2025 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2026 break;
2027 default:
2028 ibuf = NULL; // suppress warning
2029 GrCrash("Unknown geometry src type!");
2030 }
2031
2032 GrAssert(NULL != ibuf);
2033 GrAssert(!ibuf->isLocked());
2034 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002035 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002036 fHWGeometryState.fIndexBuffer = ibuf;
2037 }
2038 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002039}