blob: f2ec450a0f8eecd5f41c9e1009136a198fae5bf0 [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
bsalomon@google.com205d4602011-04-25 12:43:45 +0000364 fAALineSupport = GR_GL_SUPPORT_DESKTOP;
365
reed@google.comac10a2d2010-12-22 21:39:39 +0000366 ////////////////////////////////////////////////////////////////////////////
367 // Experiments to determine limitations that can't be queried. TODO: Make
368 // these a preprocess that generate some compile time constants.
369
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000370 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000371
twiz@google.com59a190b2011-03-14 21:23:01 +0000372 bool simpleFBOSuccess = fbo_test(128, 128);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000373 if (gPrintStartupSpew) {
374 if (!simpleFBOSuccess) {
375 GrPrintf("FBO Sanity Test: FAILED\n");
376 } else {
377 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000378 }
379 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000380 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000381
reed@google.comac10a2d2010-12-22 21:39:39 +0000382 /* Experimentation has found that some GLs that support NPOT textures
383 do not support FBOs with a NPOT texture. They report "unsupported" FBO
384 status. I don't know how to explicitly query for this. Do an
385 experiment. Note they may support NPOT with a renderbuffer but not a
386 texture. Presumably, the implementation bloats the renderbuffer
387 internally to the next POT.
388 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000389 bool fNPOTRenderTargetSupport = false;
390 if (fNPOTTextureSupport) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000391 fNPOTRenderTargetSupport = fbo_test(200, 200);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000392 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000393
bsalomon@google.com0748f212011-02-01 22:56:16 +0000394 if (gPrintStartupSpew) {
395 if (fNPOTTextureSupport) {
396 GrPrintf("NPOT textures supported\n");
397 if (fNPOTTextureTileSupport) {
398 GrPrintf("NPOT texture tiling supported\n");
399 } else {
400 GrPrintf("NPOT texture tiling NOT supported\n");
401 }
402 if (fNPOTRenderTargetSupport) {
403 GrPrintf("NPOT render targets supported\n");
404 } else {
405 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000406 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000407 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000408 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000409 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000410 }
411
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000412 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
413
reed@google.comac10a2d2010-12-22 21:39:39 +0000414 /* The iPhone 4 has a restriction that for an FBO with texture color
415 attachment with height <= 8 then the width must be <= height. Here
416 we look for such a limitation.
417 */
418 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000419 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000420 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000421 // fbo_test creates FBOs with texture bound to the color attachment
422 maxRenderSize = GrMin(maxRenderSize, fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000423
reed@google.comeeeb5a02010-12-23 15:12:59 +0000424 if (gPrintStartupSpew) {
425 GrPrintf("Small height FBO texture experiments\n");
426 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000427
twiz@google.com0f31ca72011-03-18 17:38:11 +0000428 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
429 GrGLuint w = maxRenderSize;
430 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000431 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000432 if (gPrintStartupSpew) {
433 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
434 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000435 fMinRenderTargetHeight = i;
436 break;
437 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000438 if (gPrintStartupSpew) {
439 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
440 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000441 }
442 }
443 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
444
reed@google.comeeeb5a02010-12-23 15:12:59 +0000445 if (gPrintStartupSpew) {
446 GrPrintf("Small width FBO texture experiments\n");
447 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000448 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000449 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
450 GrGLuint w = i;
451 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000452 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000453 if (gPrintStartupSpew) {
454 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
455 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000456 fMinRenderTargetWidth = i;
457 break;
458 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000459 if (gPrintStartupSpew) {
460 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
461 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000462 }
463 }
464 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
reed@google.comac10a2d2010-12-22 21:39:39 +0000465}
466
467GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000468}
469
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000470void GrGpuGL::resetContext() {
471 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000472 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000473 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000474
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000475 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000476 GR_GL(Disable(GR_GL_DEPTH_TEST));
477 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000478
twiz@google.com0f31ca72011-03-18 17:38:11 +0000479 GR_GL(Disable(GR_GL_CULL_FACE));
480 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000481 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000482
twiz@google.com0f31ca72011-03-18 17:38:11 +0000483 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000484 if (GR_GL_SUPPORT_DESKTOP) {
485 GR_GL(Disable(GR_GL_LINE_SMOOTH));
486 GR_GL(Disable(GR_GL_POINT_SMOOTH));
487 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000488 fHWAAState.fMSAAEnabled = false;
489 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000490 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000491
twiz@google.com0f31ca72011-03-18 17:38:11 +0000492 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000493 fHWDrawState.fFlagBits = 0;
494
reed@google.comac10a2d2010-12-22 21:39:39 +0000495 // we only ever use lines in hairline mode
496 GR_GL(LineWidth(1));
497
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000498 // invalid
499 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000500
reed@google.comac10a2d2010-12-22 21:39:39 +0000501 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000502 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
503 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000504
505 fHWDrawState.fBlendConstant = 0x00000000;
506 GR_GL(BlendColor(0,0,0,0));
507
reed@google.comac10a2d2010-12-22 21:39:39 +0000508 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000509
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000510 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000511
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000512 for (int s = 0; s < kNumStages; ++s) {
513 fHWDrawState.fTextures[s] = NULL;
514 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
515 -GR_ScalarMax,
516 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000517
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000518 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000519 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000520
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000521 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000522 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000523 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000524 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000525
bsalomon@google.comd302f142011-03-03 13:54:13 +0000526 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000527 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000528 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000529
530 fHWGeometryState.fIndexBuffer = NULL;
531 fHWGeometryState.fVertexBuffer = NULL;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000532 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
533 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000534 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000535
twiz@google.com0f31ca72011-03-18 17:38:11 +0000536 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000537 fHWDrawState.fRenderTarget = NULL;
538}
539
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000540GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
541
542 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
543 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
544 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
545 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
546
547 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
548 if (isRenderTarget) {
549 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
550 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
551 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
552 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
553 } else {
554 GrAssert(!isTexture); // this should have been filtered by GrContext
555 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
556 }
557 } else {
558 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
559 }
560 // we don't know what the RB ids are without glGets and we don't care
561 // since we aren't responsible for deleting them.
562 rtIDs.fStencilRenderbufferID = 0;
563 rtIDs.fMSColorRenderbufferID = 0;
564
565 rtIDs.fOwnIDs = false;
566 } else {
567 rtIDs.reset();
568 }
569
570 if (isTexture) {
571 GrGLTexture::GLTextureDesc texDesc;
572 GrGLenum dontCare;
573 if (!canBeTexture(desc.fConfig, &dontCare,
574 &texDesc.fUploadFormat,
575 &texDesc.fUploadType)) {
576 return NULL;
577 }
578
579 GrGLTexture::TexParams params;
580
581 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
582 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
583
584 texDesc.fFormat = texDesc.fFormat;
585 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
586 texDesc.fStencilBits = desc.fStencilBits;
587 texDesc.fTextureID = desc.fPlatformTexture;
588 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
589 texDesc.fOwnsID = false;
590
591 params.invalidate(); // rather than do glGets.
592
593 return new GrGLTexture(this, texDesc, rtIDs, params);
594 } else {
595 GrGLIRect viewport;
596 viewport.fLeft = 0;
597 viewport.fBottom = 0;
598 viewport.fWidth = desc.fWidth;
599 viewport.fHeight = desc.fHeight;
600
601 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
602 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
603 viewport, NULL);
604 }
605}
606
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000607GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(
reed@google.comac10a2d2010-12-22 21:39:39 +0000608 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000609 int stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000610 bool isMultisampled,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000611 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000612 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000613 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
614 rtIDs.fStencilRenderbufferID = 0;
615 rtIDs.fMSColorRenderbufferID = 0;
616 rtIDs.fTexFBOID = 0;
617 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000618 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000619
620 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000621 viewport.fLeft = 0;
622 viewport.fBottom = 0;
623 viewport.fWidth = width;
624 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000625
twiz@google.com0f31ca72011-03-18 17:38:11 +0000626 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
627 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000628
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000629 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
630 isMultisampled, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000631}
632
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000633GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000634
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000635 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000636
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000637 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000638 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
639 rtIDs.fMSColorRenderbufferID = 0;
640 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000641
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000642 GrGLIRect viewport;
643 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000644 GrGLuint stencilBits;
645 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000646
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000647 GrGLint samples;
648 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
649
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000650 rtIDs.fOwnIDs = false;
651
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000652 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
653 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000654}
655
bsalomon@google.com5782d712011-01-21 21:03:59 +0000656///////////////////////////////////////////////////////////////////////////////
657
twiz@google.com0f31ca72011-03-18 17:38:11 +0000658static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000659
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000660struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000661 GrGLenum fEnum;
662 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000663 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000664};
665
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000666const StencilFormat* GrGLStencilFormats() {
667 // defines stencil formats from more to less preferred
668 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000669 {GR_GL_STENCIL_INDEX8, 8, false},
670 {GR_GL_STENCIL_INDEX16, 16, false},
671 {GR_GL_DEPTH24_STENCIL8, 8, true },
672 {GR_GL_STENCIL_INDEX4, 4, false},
673 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
674 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
675 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000676 };
677
678 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000679 {GR_GL_STENCIL_INDEX8, 8, false},
680 {GR_GL_DEPTH24_STENCIL8, 8, true },
681 {GR_GL_STENCIL_INDEX4, 4, false},
682 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000683 };
684
685 if (GR_GL_SUPPORT_DESKTOP) {
686 return desktopStencilFormats;
687 } else {
688 return esStencilFormats;
689 }
690}
691
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000692// good to set a break-point here to know when createTexture fails
693static GrTexture* return_null_texture() {
694// GrAssert(!"null texture");
695 return NULL;
696}
697
698#if GR_DEBUG
699static size_t as_size_t(int x) {
700 return x;
701}
702#endif
703
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000704GrTexture* GrGpuGL::onCreateTexture(const TextureDesc& desc,
705 const void* srcData,
706 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000707
708#if GR_COLLECT_STATS
709 ++fStats.fTextureCreateCnt;
710#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000711
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000712 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000713
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000714 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000715 GR_GL_NEAREST,
716 GR_GL_CLAMP_TO_EDGE,
717 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000718 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000719
reed@google.comac10a2d2010-12-22 21:39:39 +0000720 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000721 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000722
723 glDesc.fContentWidth = desc.fWidth;
724 glDesc.fContentHeight = desc.fHeight;
725 glDesc.fAllocWidth = desc.fWidth;
726 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000727 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000728 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000729 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000730
731 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
732 if (!canBeTexture(desc.fFormat,
733 &internalFormat,
734 &glDesc.fUploadFormat,
735 &glDesc.fUploadType)) {
736 return return_null_texture();
737 }
738
739 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000740 GrGLint samples = fAASamples[desc.fAALevel];
reed@google.comac10a2d2010-12-22 21:39:39 +0000741 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
742 GrPrintf("AA RT requested but not supported on this platform.");
743 }
744
745 GR_GL(GenTextures(1, &glDesc.fTextureID));
746 if (!glDesc.fTextureID) {
747 return return_null_texture();
748 }
749
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000750 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000751
reed@google.com5e762232011-04-04 18:15:49 +0000752 // in case we need a temporary, trimmed copy of the src pixels
753 GrAutoSMalloc<128 * 128> trimStorage;
754
reed@google.comac10a2d2010-12-22 21:39:39 +0000755 /*
756 * check if our srcData has extra bytes past each row. If so, we need
757 * to trim those off here, since GL doesn't let us pass the rowBytes as
758 * a parameter to glTexImage2D
759 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000760 if (GR_GL_SUPPORT_DESKTOP) {
761 if (srcData) {
762 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
763 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000764 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000765 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000766 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
767 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000768 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000769 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000770 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000771 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000772 for (uint32_t y = 0; y < desc.fHeight; y++) {
773 memcpy(dst, src, trimRowBytes);
774 src += rowBytes;
775 dst += trimRowBytes;
776 }
777 // now point srcData to our trimmed version
778 srcData = trimStorage.get();
779 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000780 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000781
reed@google.comac10a2d2010-12-22 21:39:39 +0000782 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000783 if (!this->npotRenderTargetSupport()) {
784 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
785 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
786 }
787
reed@google.comac10a2d2010-12-22 21:39:39 +0000788 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
789 glDesc.fAllocWidth);
790 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
791 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000792 } else if (!this->npotTextureSupport()) {
793 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
794 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000795 }
796
twiz@google.com0f31ca72011-03-18 17:38:11 +0000797 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
798 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
799 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000800 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000801 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
802 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000803 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000804 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
805 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000806 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000807 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
808 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000809 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000810
twiz@google.com0f31ca72011-03-18 17:38:11 +0000811 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000812 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000813 supports8BitPalette()) {
814 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
815 GrAssert(desc.fWidth == glDesc.fAllocWidth);
816 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000817 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
818 kColorTableSize;
819 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000820 glDesc.fAllocWidth, glDesc.fAllocHeight,
821 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000822 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000823 } else {
824 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
825 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000826 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000827 glDesc.fAllocWidth, glDesc.fAllocHeight,
828 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000829 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000830 desc.fHeight, glDesc.fUploadFormat,
831 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000832 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000833
834 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
835 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
836 uint32_t maxTexels = extraW * extraH;
837 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
838 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
839
840 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
841
842 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
843 if (extraH) {
844 uint8_t* lastRowStart = (uint8_t*) srcData +
845 (desc.fHeight - 1) * rowSize;
846 uint8_t* extraRowStart = (uint8_t*)texels.get();
847
848 for (uint32_t i = 0; i < extraH; ++i) {
849 memcpy(extraRowStart, lastRowStart, rowSize);
850 extraRowStart += rowSize;
851 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000852 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000853 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
854 texels.get()));
855 }
856 if (extraW) {
857 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
858 uint8_t* extraTexel = (uint8_t*)texels.get();
859 for (uint32_t j = 0; j < desc.fHeight; ++j) {
860 for (uint32_t i = 0; i < extraW; ++i) {
861 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
862 extraTexel += glDesc.fUploadByteCount;
863 }
864 edgeTexel += rowSize;
865 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000866 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000867 desc.fHeight, glDesc.fUploadFormat,
868 glDesc.fUploadType, texels.get()));
869 }
870 if (extraW && extraH) {
871 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
872 - glDesc.fUploadByteCount;
873 uint8_t* extraTexel = (uint8_t*)texels.get();
874 for (uint32_t i = 0; i < extraW*extraH; ++i) {
875 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
876 extraTexel += glDesc.fUploadByteCount;
877 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000878 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000879 extraW, extraH, glDesc.fUploadFormat,
880 glDesc.fUploadType, texels.get()));
881 }
882
883 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000884 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000885 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
886 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000887 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000888 }
889 }
890
891 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
892
893 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
894 rtIDs.fStencilRenderbufferID = 0;
895 rtIDs.fMSColorRenderbufferID = 0;
896 rtIDs.fRTFBOID = 0;
897 rtIDs.fTexFBOID = 0;
898 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000899 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000900
901 if (renderTarget) {
902#if GR_COLLECT_STATS
903 ++fStats.fRenderTargetCreateCnt;
904#endif
905 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000906 GrGLenum status;
907 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000908
909 // If need have both RT flag and srcData we have
910 // to invert the data before uploading because FBO
911 // will be rendered bottom up
912 GrAssert(NULL == srcData);
913 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
914
twiz@google.com59a190b2011-03-14 21:23:01 +0000915 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000916 GrAssert(rtIDs.fTexFBOID);
917
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000918 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000919 // to one and then resolve to the texture bound to the other.
920 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000921 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000923 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000924 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
925 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000926 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000927 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000928 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
929 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000930 return return_null_texture();
931 }
932 } else {
933 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
934 }
bsalomon@google.comf6a7c112011-03-24 16:14:10 +0000935 if (!(kNoStencil_TextureFlag & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000936 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000937 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000938 }
939
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000940 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000941 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000942 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000943 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000944
twiz@google.com0f31ca72011-03-18 17:38:11 +0000945 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000946
947 const StencilFormat* stencilFormats = GrGLStencilFormats();
948 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000949 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000950 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000951 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000952 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000953 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000954 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000955 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000956 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000957 glDesc.fAllocWidth,
958 glDesc.fAllocHeight));
959 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000960 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000961 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000962 glDesc.fAllocWidth,
963 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000964 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000965 err = GrGLGetGLInterface()->fGetError();
966 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000967 continue;
968 }
969 }
970 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
971 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000972 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000973 rtIDs.fMSColorRenderbufferID));
974 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000975 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000976 samples,
977 msColorRenderbufferFormat,
978 glDesc.fAllocWidth,
979 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000980 err = GrGLGetGLInterface()->fGetError();
981 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000982 continue;
983 }
984 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000985 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000986
987#if GR_COLLECT_STATS
988 ++fStats.fRenderTargetChngCnt;
989#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000990 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
991 GR_GL_COLOR_ATTACHMENT0,
992 GR_GL_TEXTURE_2D,
993 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000994 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000995 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
996 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000997 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
998 status, desc.fWidth, desc.fHeight);
999 continue;
1000 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001001 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001002 #if GR_COLLECT_STATS
1003 ++fStats.fRenderTargetChngCnt;
1004 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001005 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1006 GR_GL_COLOR_ATTACHMENT0,
1007 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001008 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001009
1010 }
1011 if (rtIDs.fStencilRenderbufferID) {
1012 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001013 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1014 GR_GL_STENCIL_ATTACHMENT,
1015 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001016 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001017 // if it is a packed format bind to depth also, otherwise
1018 // we may get an unsupported fbo completeness result
1019 if (stencilFormats[i].fPacked) {
1020 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1021 GR_GL_DEPTH_ATTACHMENT,
1022 GR_GL_RENDERBUFFER,
1023 rtIDs.fStencilRenderbufferID));
1024 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001025 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001026 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001027
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001028 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001029 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1030 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001031 // undo the depth bind
1032 if (rtIDs.fStencilRenderbufferID &&
1033 stencilFormats[i].fPacked) {
1034 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1035 GR_GL_DEPTH_ATTACHMENT,
1036 GR_GL_RENDERBUFFER,
1037 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001038 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001039 continue;
1040 }
1041 // we're successful!
1042 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001043 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001044 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001045 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001046 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001047 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001048 }
1049 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001050 break;
1051 }
1052 if (failed) {
1053 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001054 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001055 }
1056 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001057 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001058 }
1059 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001060 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001061 }
1062 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001063 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001064 }
1065 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1066 return return_null_texture();
1067 }
1068 }
1069#ifdef TRACE_TEXTURE_CREATION
1070 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1071 tex->fTextureID, width, height, tex->fUploadByteCount);
1072#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001073 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001074
1075 if (0 != rtIDs.fTexFBOID) {
1076 GrRenderTarget* rt = tex->asRenderTarget();
1077 // We've messed with FBO state but may not have set the correct viewport
1078 // so just dirty the rendertarget state to force a resend.
1079 fHWDrawState.fRenderTarget = NULL;
1080
1081 // clear the new stencil buffer if we have one
bsalomon@google.comf6a7c112011-03-24 16:14:10 +00001082 if (!(desc.fFlags & kNoStencil_TextureFlag)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001083 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1084 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001085 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001086 fCurrDrawState.fRenderTarget = rtSave;
1087 }
1088 }
1089 return tex;
1090}
1091
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001092GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001093 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 GR_GL(GenBuffers(1, &id));
1095 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001096 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001097 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001098 GrGLClearErr();
1099 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001100 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1101 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1102 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001103 GR_GL(DeleteBuffers(1, &id));
1104 // deleting bound buffer does implicit bind to 0
1105 fHWGeometryState.fVertexBuffer = NULL;
1106 return NULL;
1107 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001108 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001109 size, dynamic);
1110 fHWGeometryState.fVertexBuffer = vertexBuffer;
1111 return vertexBuffer;
1112 }
1113 return NULL;
1114}
1115
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001116GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001117 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001118 GR_GL(GenBuffers(1, &id));
1119 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001120 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001121 GrGLClearErr();
1122 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001123 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1124 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1125 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001126 GR_GL(DeleteBuffers(1, &id));
1127 // deleting bound buffer does implicit bind to 0
1128 fHWGeometryState.fIndexBuffer = NULL;
1129 return NULL;
1130 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001131 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001132 size, dynamic);
1133 fHWGeometryState.fIndexBuffer = indexBuffer;
1134 return indexBuffer;
1135 }
1136 return NULL;
1137}
1138
reed@google.comac10a2d2010-12-22 21:39:39 +00001139void GrGpuGL::flushScissor(const GrIRect* rect) {
1140 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001141 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001142 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001143
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001144 GrGLIRect scissor;
1145 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001146 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001147 rect->width(), rect->height());
1148 if (scissor.contains(vp)) {
1149 rect = NULL;
1150 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001151 }
1152
1153 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001154 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001155 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 fHWBounds.fScissorRect = scissor;
1157 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001158 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001159 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001160 fHWBounds.fScissorEnabled = true;
1161 }
1162 } else {
1163 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001164 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001165 fHWBounds.fScissorEnabled = false;
1166 }
1167 }
1168}
1169
bsalomon@google.com398109c2011-04-14 18:40:27 +00001170void GrGpuGL::onClear(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001171 if (NULL == fCurrDrawState.fRenderTarget) {
1172 return;
1173 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001174 flushRenderTarget();
1175 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001176 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001177 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001178 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001179 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001180 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001181 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1182 GrColorUnpackG(color)/255.f,
1183 GrColorUnpackB(color)/255.f,
1184 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001185 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001186}
1187
bsalomon@google.com398109c2011-04-14 18:40:27 +00001188void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001189 if (NULL == fCurrDrawState.fRenderTarget) {
1190 return;
1191 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001192 flushRenderTarget();
1193 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001194 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001195 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001196 }
1197 GR_GL(StencilMask(mask));
1198 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001199 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001200 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001201}
1202
bsalomon@google.com398109c2011-04-14 18:40:27 +00001203void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001204 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001205#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001206 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001207 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001208 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001209#else
1210 // we could just clear the clip bit but when we go through
1211 // angle a partial stencil mask will cause clears to be
1212 // turned into draws. Our contract on GrDrawTarget says that
1213 // changing the clip between stencil passes may or may not
1214 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001215 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001216#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001217 flushRenderTarget();
1218 flushScissor(&rect);
1219 GR_GL(StencilMask(clipStencilMask));
1220 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001221 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001222 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001223}
1224
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001225void GrGpuGL::onForceRenderTargetFlush() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001226 flushRenderTarget();
1227}
1228
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001229bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1230 int left, int top, int width, int height,
1231 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001232 GrGLenum internalFormat; // we don't use this for glReadPixels
1233 GrGLenum format;
1234 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001235 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1236 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001237 }
1238 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1239 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1240 switch (tgt->getResolveType()) {
1241 case GrGLRenderTarget::kCantResolve_ResolveType:
1242 return false;
1243 case GrGLRenderTarget::kAutoResolves_ResolveType:
1244 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1245 fCurrDrawState.fRenderTarget = target;
1246 flushRenderTarget();
1247 break;
1248 case GrGLRenderTarget::kCanResolve_ResolveType:
1249 resolveRenderTarget(tgt);
1250 // we don't track the state of the READ FBO ID.
1251 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1252 break;
1253 default:
1254 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001255 }
1256
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001257 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001258
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001259 // the read rect is viewport-relative
1260 GrGLIRect readRect;
1261 readRect.setRelativeTo(glvp, left, top, width, height);
1262 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001263 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001264 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001265
1266 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1267 // API presents top-to-bottom
1268 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001269 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001270 GrAutoMalloc rowStorage(stride);
1271 void* tmp = rowStorage.get();
1272
1273 const int halfY = height >> 1;
1274 char* top = reinterpret_cast<char*>(buffer);
1275 char* bottom = top + (height - 1) * stride;
1276 for (int y = 0; y < halfY; y++) {
1277 memcpy(tmp, top, stride);
1278 memcpy(top, bottom, stride);
1279 memcpy(bottom, tmp, stride);
1280 top += stride;
1281 bottom -= stride;
1282 }
1283 }
1284 return true;
1285}
1286
1287void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001288
1289 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1290
reed@google.comac10a2d2010-12-22 21:39:39 +00001291 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1292 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001293 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001294 #if GR_COLLECT_STATS
1295 ++fStats.fRenderTargetChngCnt;
1296 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001297 rt->flagAsNeedingResolve();
reed@google.comac10a2d2010-12-22 21:39:39 +00001298 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001299 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1300 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001301 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1302 }
1303 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001304 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001305 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001306 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001307 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001308 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001309 fHWBounds.fViewportRect = vp;
1310 }
1311 }
1312}
1313
twiz@google.com0f31ca72011-03-18 17:38:11 +00001314GrGLenum gPrimitiveType2GLMode[] = {
1315 GR_GL_TRIANGLES,
1316 GR_GL_TRIANGLE_STRIP,
1317 GR_GL_TRIANGLE_FAN,
1318 GR_GL_POINTS,
1319 GR_GL_LINES,
1320 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001321};
1322
bsalomon@google.comd302f142011-03-03 13:54:13 +00001323#define SWAP_PER_DRAW 0
1324
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001325#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001326 #if GR_MAC_BUILD
1327 #include <AGL/agl.h>
1328 #elif GR_WIN32_BUILD
1329 void SwapBuf() {
1330 DWORD procID = GetCurrentProcessId();
1331 HWND hwnd = GetTopWindow(GetDesktopWindow());
1332 while(hwnd) {
1333 DWORD wndProcID = 0;
1334 GetWindowThreadProcessId(hwnd, &wndProcID);
1335 if(wndProcID == procID) {
1336 SwapBuffers(GetDC(hwnd));
1337 }
1338 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1339 }
1340 }
1341 #endif
1342#endif
1343
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001344void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1345 uint32_t startVertex,
1346 uint32_t startIndex,
1347 uint32_t vertexCount,
1348 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001349 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1350
twiz@google.com0f31ca72011-03-18 17:38:11 +00001351 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001352
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001353 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1354 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1355
1356 // our setupGeometry better have adjusted this to zero since
1357 // DrawElements always draws from the begining of the arrays for idx 0.
1358 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001359
1360 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001361 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001362#if SWAP_PER_DRAW
1363 glFlush();
1364 #if GR_MAC_BUILD
1365 aglSwapBuffers(aglGetCurrentContext());
1366 int set_a_break_pt_here = 9;
1367 aglSwapBuffers(aglGetCurrentContext());
1368 #elif GR_WIN32_BUILD
1369 SwapBuf();
1370 int set_a_break_pt_here = 9;
1371 SwapBuf();
1372 #endif
1373#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001374}
1375
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001376void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1377 uint32_t startVertex,
1378 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001379 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1380
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001381 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1382
1383 // our setupGeometry better have adjusted this to zero.
1384 // DrawElements doesn't take an offset so we always adjus the startVertex.
1385 GrAssert(0 == startVertex);
1386
1387 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1388 // account for startVertex in the DrawElements case. So we always
1389 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001390 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001391#if SWAP_PER_DRAW
1392 glFlush();
1393 #if GR_MAC_BUILD
1394 aglSwapBuffers(aglGetCurrentContext());
1395 int set_a_break_pt_here = 9;
1396 aglSwapBuffers(aglGetCurrentContext());
1397 #elif GR_WIN32_BUILD
1398 SwapBuf();
1399 int set_a_break_pt_here = 9;
1400 SwapBuf();
1401 #endif
1402#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001403}
1404
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001405void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001406
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001407 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001408 GrAssert(kNone_MSFBO != fMSFBOType);
1409 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001410 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001411 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001412 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001413 rt->textureFBOID()));
1414 #if GR_COLLECT_STATS
1415 ++fStats.fRenderTargetChngCnt;
1416 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001417 // make sure we go through flushRenderTarget() since we've modified
1418 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001419 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001420 const GrGLIRect& vp = rt->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001421
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001422 if (kAppleES_MSFBO == fMSFBOType) {
1423 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001424 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001425 GR_GL(Scissor(vp.fLeft, vp.fBottom,
1426 vp.fWidth, vp.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001427 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001428 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001429 fHWBounds.fScissorEnabled = true;
1430 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001431 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001432 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001433 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1434 flushScissor(NULL);
1435 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001436 int right = vp.fLeft + vp.fWidth;
1437 int top = vp.fBottom + vp.fHeight;
1438 GR_GL(BlitFramebuffer(vp.fLeft, vp.fBottom, right, top,
1439 vp.fLeft, vp.fBottom, right, top,
1440 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001441 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001442 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001443 }
1444}
1445
twiz@google.com0f31ca72011-03-18 17:38:11 +00001446static const GrGLenum grToGLStencilFunc[] = {
1447 GR_GL_ALWAYS, // kAlways_StencilFunc
1448 GR_GL_NEVER, // kNever_StencilFunc
1449 GR_GL_GREATER, // kGreater_StencilFunc
1450 GR_GL_GEQUAL, // kGEqual_StencilFunc
1451 GR_GL_LESS, // kLess_StencilFunc
1452 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1453 GR_GL_EQUAL, // kEqual_StencilFunc,
1454 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001455};
1456GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1457GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1458GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1459GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1460GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1461GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1462GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1463GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1464GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1465
twiz@google.com0f31ca72011-03-18 17:38:11 +00001466static const GrGLenum grToGLStencilOp[] = {
1467 GR_GL_KEEP, // kKeep_StencilOp
1468 GR_GL_REPLACE, // kReplace_StencilOp
1469 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1470 GR_GL_INCR, // kIncClamp_StencilOp
1471 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1472 GR_GL_DECR, // kDecClamp_StencilOp
1473 GR_GL_ZERO, // kZero_StencilOp
1474 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001475};
1476GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1477GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1478GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1479GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1480GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1481GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1482GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1483GR_STATIC_ASSERT(6 == kZero_StencilOp);
1484GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1485
reed@google.comac10a2d2010-12-22 21:39:39 +00001486void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001487 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001488
1489 // use stencil for clipping if clipping is enabled and the clip
1490 // has been written into the stencil.
1491 bool stencilClip = fClipState.fClipInStencil &&
1492 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001493 bool stencilChange = fHWStencilClip != stencilClip ||
1494 fHWDrawState.fStencilSettings != *settings ||
1495 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1496 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001497
1498 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001499
bsalomon@google.comd302f142011-03-03 13:54:13 +00001500 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1501 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001502
bsalomon@google.comd302f142011-03-03 13:54:13 +00001503 if (settings->isDisabled()) {
1504 if (stencilClip) {
1505 settings = &gClipStencilSettings;
1506 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001507 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001508
1509 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001510 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001511 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001512 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001513 #if GR_DEBUG
1514 if (!fStencilWrapOpsSupport) {
1515 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1516 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1517 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1518 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1519 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1520 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1521 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1522 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1523 }
1524 #endif
1525 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1526 GrAssert(stencilBits ||
1527 (GrStencilSettings::gDisabled ==
1528 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001529 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1530 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001531
1532 unsigned int frontRef = settings->fFrontFuncRef;
1533 unsigned int frontMask = settings->fFrontFuncMask;
1534 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001535 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001536
1537 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1538
1539 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1540 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1541 } else {
1542 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1543
1544 ConvertStencilFuncAndMask(settings->fFrontFunc,
1545 stencilClip,
1546 clipStencilMask,
1547 userStencilMask,
1548 &frontRef,
1549 &frontMask);
1550 frontWriteMask &= userStencilMask;
1551 }
1552 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001553 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001554 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001555 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001556 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001557 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001558 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001559 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001560 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001561 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001562
1563 unsigned int backRef = settings->fBackFuncRef;
1564 unsigned int backMask = settings->fBackFuncMask;
1565 unsigned int backWriteMask = settings->fBackWriteMask;
1566
1567
1568 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1569 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1570 backFunc = grToGLStencilFunc[settings->fBackFunc];
1571 } else {
1572 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1573 ConvertStencilFuncAndMask(settings->fBackFunc,
1574 stencilClip,
1575 clipStencilMask,
1576 userStencilMask,
1577 &backRef,
1578 &backMask);
1579 backWriteMask &= userStencilMask;
1580 }
1581
twiz@google.com0f31ca72011-03-18 17:38:11 +00001582 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1583 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1584 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1585 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1586 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001587 grToGLStencilOp[settings->fFrontPassOp],
1588 grToGLStencilOp[settings->fFrontPassOp]));
1589
twiz@google.com0f31ca72011-03-18 17:38:11 +00001590 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001591 grToGLStencilOp[settings->fBackPassOp],
1592 grToGLStencilOp[settings->fBackPassOp]));
1593 } else {
1594 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1595 GR_GL(StencilMask(frontWriteMask));
1596 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1597 grToGLStencilOp[settings->fFrontPassOp],
1598 grToGLStencilOp[settings->fFrontPassOp]));
1599 }
1600 }
1601 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001602 fHWStencilClip = stencilClip;
1603 }
1604}
1605
bsalomon@google.com0650e812011-04-08 18:07:53 +00001606bool GrGpuGL::useSmoothLines() {
1607 // there is a conflict between using smooth lines and our use of
1608 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1609 // but not in a premul-alpha way. So we only use them when our alpha
1610 // is 0xff.
1611
1612 // TODO: write a smarter line frag shader.
1613
1614 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1615 canDisableBlend();
1616}
1617
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001618void GrGpuGL::flushAAState(GrPrimitiveType type) {
1619 if (GR_GL_SUPPORT_DESKTOP) {
1620 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1621 // smooth lines.
1622
1623 // we prefer smooth lines over multisampled lines
1624 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001625 if (GrIsPrimTypeLines(type)) {
1626 bool smooth = useSmoothLines();
1627 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001628 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1629 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001630 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001631 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1632 fHWAAState.fSmoothLineEnabled = false;
1633 }
1634 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1635 fHWAAState.fMSAAEnabled) {
1636 GR_GL(Disable(GR_GL_MULTISAMPLE));
1637 fHWAAState.fMSAAEnabled = false;
1638 }
1639 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1640 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1641 fHWAAState.fMSAAEnabled) {
1642 if (fHWAAState.fMSAAEnabled) {
1643 GR_GL(Disable(GR_GL_MULTISAMPLE));
1644 fHWAAState.fMSAAEnabled = false;
1645 } else {
1646 GR_GL(Enable(GR_GL_MULTISAMPLE));
1647 fHWAAState.fMSAAEnabled = true;
1648 }
1649 }
1650 }
1651}
1652
bsalomon@google.com0650e812011-04-08 18:07:53 +00001653void GrGpuGL::flushBlend(GrPrimitiveType type) {
1654 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1655 if (fHWBlendDisabled) {
1656 GR_GL(Enable(GR_GL_BLEND));
1657 fHWBlendDisabled = false;
1658 }
1659 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1660 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1661 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1662 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1663 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1664 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1665 }
1666 } else {
1667 bool blendOff = canDisableBlend();
1668 if (fHWBlendDisabled != blendOff) {
1669 if (blendOff) {
1670 GR_GL(Disable(GR_GL_BLEND));
1671 } else {
1672 GR_GL(Enable(GR_GL_BLEND));
1673 }
1674 fHWBlendDisabled = blendOff;
1675 }
1676 if (!blendOff) {
1677 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1678 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1679 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1680 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1681 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1682 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1683 }
1684 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1685 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1686 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1687
1688 float c[] = {
1689 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1690 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1691 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1692 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1693 };
1694 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1695 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1696 }
1697 }
1698 }
1699}
1700
bsalomon@google.comffca4002011-02-22 20:34:01 +00001701bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001702
1703 // GrGpu::setupClipAndFlushState should have already checked this
1704 // and bailed if not true.
1705 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001706
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001707 for (int s = 0; s < kNumStages; ++s) {
1708 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001709
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001710 // bind texture and set sampler state
1711 if (usingTexture) {
1712 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001713
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001714 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001715 // if we created a rt/tex and rendered to it without using a
1716 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001717 // the last bound texture, but it needs resolving. So keep this
1718 // out of the "last != next" check.
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001719 GrGLRenderTarget* texRT =
1720 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1721 if (NULL != texRT) {
1722 resolveRenderTarget(texRT);
1723 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001724
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001725 if (fHWDrawState.fTextures[s] != nextTexture) {
1726 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001727 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001728 #if GR_COLLECT_STATS
1729 ++fStats.fTextureChngCnt;
1730 #endif
1731 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1732 fHWDrawState.fTextures[s] = nextTexture;
1733 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001734
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001735 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001736 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001737 nextTexture->getTexParams();
1738 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001739
twiz@google.com0f31ca72011-03-18 17:38:11 +00001740 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1741 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001742 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001743 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001744 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001745 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001746
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001747 if (newTexParams.fFilter != oldTexParams.fFilter) {
1748 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001749 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1750 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001751 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001752 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1753 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001754 newTexParams.fFilter));
1755 }
1756 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1757 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001758 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1759 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001760 newTexParams.fWrapS));
1761 }
1762 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1763 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001764 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1765 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001766 newTexParams.fWrapT));
1767 }
1768 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001769
1770 // The texture matrix has to compensate for texture width/height
1771 // and NPOT-embedded-in-POT
1772 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001773 } else {
1774 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001775 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001776 }
1777 }
1778 }
1779
1780 flushRenderTarget();
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001781 flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001782 flushBlend(type);
1783
reed@google.comac10a2d2010-12-22 21:39:39 +00001784 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1785 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1786 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001787 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001788 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001789 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001790 }
1791 }
1792
bsalomon@google.comd302f142011-03-03 13:54:13 +00001793 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1794 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001795 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001796 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001797 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001798 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001799 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001800 }
1801 GR_GL(ColorMask(mask, mask, mask, mask));
1802 }
1803
bsalomon@google.comd302f142011-03-03 13:54:13 +00001804 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1805 switch (fCurrDrawState.fDrawFace) {
1806 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001807 GR_GL(Enable(GR_GL_CULL_FACE));
1808 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001809 break;
1810 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001811 GR_GL(Enable(GR_GL_CULL_FACE));
1812 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001813 break;
1814 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001815 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001816 break;
1817 default:
1818 GrCrash("Unknown draw face.");
1819 }
1820 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1821 }
1822
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001823#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001824 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001825 for (int s = 0; s < kNumStages; ++s) {
1826 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1827 NULL == fCurrDrawState.fRenderTarget ||
1828 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001829 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001830 fCurrDrawState.fRenderTarget);
1831 }
1832#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001833
reed@google.comac10a2d2010-12-22 21:39:39 +00001834 flushStencil();
1835
bsalomon@google.comd302f142011-03-03 13:54:13 +00001836 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001837 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001838 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001839}
1840
1841void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001842 if (fHWGeometryState.fVertexBuffer != buffer) {
1843 fHWGeometryState.fArrayPtrsDirty = true;
1844 fHWGeometryState.fVertexBuffer = buffer;
1845 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001846}
1847
1848void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001849 if (fHWGeometryState.fVertexBuffer == buffer) {
1850 // deleting bound buffer does implied bind to 0
1851 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001852 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001853 }
1854}
1855
1856void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1857 fGeometrySrc.fIndexBuffer = buffer;
1858}
1859
1860void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001861 if (fHWGeometryState.fIndexBuffer == buffer) {
1862 // deleting bound buffer does implied bind to 0
1863 fHWGeometryState.fIndexBuffer = NULL;
1864 }
1865}
1866
reed@google.comac10a2d2010-12-22 21:39:39 +00001867void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1868 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001869 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001870 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001871 }
1872 if (fHWDrawState.fRenderTarget == renderTarget) {
1873 fHWDrawState.fRenderTarget = NULL;
1874 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001875}
1876
1877void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001878 for (int s = 0; s < kNumStages; ++s) {
1879 if (fCurrDrawState.fTextures[s] == texture) {
1880 fCurrDrawState.fTextures[s] = NULL;
1881 }
1882 if (fHWDrawState.fTextures[s] == texture) {
1883 // deleting bound texture does implied bind to 0
1884 fHWDrawState.fTextures[s] = NULL;
1885 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001886 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001887}
1888
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001889bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001890 GrGLenum* internalFormat,
1891 GrGLenum* format,
1892 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001893 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001894 case kRGBA_8888_GrPixelConfig:
1895 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001896 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001897 if (GR_GL_SUPPORT_ES) {
1898 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1899 // format for a BGRA is BGRA not RGBA (as on desktop)
1900 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1901 } else {
1902 *internalFormat = GR_GL_RGBA;
1903 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001904 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001905 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001906 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001907 *format = GR_GL_RGB;
1908 *internalFormat = GR_GL_RGB;
1909 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001910 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001911 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001912 *format = GR_GL_RGBA;
1913 *internalFormat = GR_GL_RGBA;
1914 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001915 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001916 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001917 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001918 *format = GR_GL_PALETTE8_RGBA8;
1919 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001920 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001921 } else {
1922 return false;
1923 }
1924 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001925 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001926 *format = GR_GL_ALPHA;
1927 *internalFormat = GR_GL_ALPHA;
1928 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001929 break;
1930 default:
1931 return false;
1932 }
1933 return true;
1934}
1935
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001936void GrGpuGL::setTextureUnit(int unit) {
1937 GrAssert(unit >= 0 && unit < kNumStages);
1938 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001939 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001940 fActiveTextureUnitIdx = unit;
1941 }
1942}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001943
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001944void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001945 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1946 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001947 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1948 }
1949}
1950
reed@google.comac10a2d2010-12-22 21:39:39 +00001951/* On ES the internalFormat and format must match for TexImage and we use
1952 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1953 decide the internalFormat. However, on ES internalFormat for
1954 RenderBufferStorage* has to be a specific format (not a base format like
1955 GL_RGBA).
1956 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001957bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001958 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001959 case kRGBA_8888_GrPixelConfig:
1960 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001961 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001962 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001963 return true;
1964 } else {
1965 return false;
1966 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001967 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001968 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1969 // with FBO extension desktop GL has
1970 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001971 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001972 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001973 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001974 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001975 return true;
1976 default:
1977 return false;
1978 }
1979}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001980
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001981void GrGpuGL::resetDirtyFlags() {
1982 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1983}
1984
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001985void GrGpuGL::setBuffers(bool indexed,
1986 int* extraVertexOffset,
1987 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001988
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001989 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001990
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001991 GrGLVertexBuffer* vbuf;
1992 switch (fGeometrySrc.fVertexSrc) {
1993 case kBuffer_GeometrySrcType:
1994 *extraVertexOffset = 0;
1995 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1996 break;
1997 case kArray_GeometrySrcType:
1998 case kReserved_GeometrySrcType:
1999 finalizeReservedVertices();
2000 *extraVertexOffset = fCurrPoolStartVertex;
2001 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2002 break;
2003 default:
2004 vbuf = NULL; // suppress warning
2005 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002006 }
2007
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002008 GrAssert(NULL != vbuf);
2009 GrAssert(!vbuf->isLocked());
2010 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002011 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002012 fHWGeometryState.fArrayPtrsDirty = true;
2013 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002014 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002015
2016 if (indexed) {
2017 GrAssert(NULL != extraIndexOffset);
2018
2019 GrGLIndexBuffer* ibuf;
2020 switch (fGeometrySrc.fIndexSrc) {
2021 case kBuffer_GeometrySrcType:
2022 *extraIndexOffset = 0;
2023 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2024 break;
2025 case kArray_GeometrySrcType:
2026 case kReserved_GeometrySrcType:
2027 finalizeReservedIndices();
2028 *extraIndexOffset = fCurrPoolStartIndex;
2029 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2030 break;
2031 default:
2032 ibuf = NULL; // suppress warning
2033 GrCrash("Unknown geometry src type!");
2034 }
2035
2036 GrAssert(NULL != ibuf);
2037 GrAssert(!ibuf->isLocked());
2038 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002039 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002040 fHWGeometryState.fIndexBuffer = ibuf;
2041 }
2042 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002043}