blob: b0ec2bc9089862f68530f6b9734c57db478535d2 [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
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000226 GR_STATIC_ASSERT(0 == kNone_GrAALevel);
227 GR_STATIC_ASSERT(1 == kLow_GrAALevel);
228 GR_STATIC_ASSERT(2 == kMed_GrAALevel);
229 GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
reed@google.comac10a2d2010-12-22 21:39:39 +0000230
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 ) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000271 fAASamples[kNone_GrAALevel] = 0;
272 fAASamples[kLow_GrAALevel] = GrMax(2,
273 GrFixedFloorToInt((GR_FixedHalf) *
274 maxSamples));
275 fAASamples[kMed_GrAALevel] = GrMax(2,
276 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
277 maxSamples));
278 fAASamples[kHigh_GrAALevel] = maxSamples;
reed@google.comac10a2d2010-12-22 21:39:39 +0000279 }
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;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000532
twiz@google.com0f31ca72011-03-18 17:38:11 +0000533 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
534 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000535
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000536 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000537
twiz@google.com0f31ca72011-03-18 17:38:11 +0000538 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000539 fHWDrawState.fRenderTarget = NULL;
540}
541
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000542GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
543
544 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
545 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
546 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
547 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
548
549 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
550 if (isRenderTarget) {
551 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
552 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
553 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
554 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
555 } else {
556 GrAssert(!isTexture); // this should have been filtered by GrContext
557 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
558 }
559 } else {
560 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
561 }
562 // we don't know what the RB ids are without glGets and we don't care
563 // since we aren't responsible for deleting them.
564 rtIDs.fStencilRenderbufferID = 0;
565 rtIDs.fMSColorRenderbufferID = 0;
566
567 rtIDs.fOwnIDs = false;
568 } else {
569 rtIDs.reset();
570 }
571
572 if (isTexture) {
573 GrGLTexture::GLTextureDesc texDesc;
574 GrGLenum dontCare;
575 if (!canBeTexture(desc.fConfig, &dontCare,
576 &texDesc.fUploadFormat,
577 &texDesc.fUploadType)) {
578 return NULL;
579 }
580
581 GrGLTexture::TexParams params;
582
583 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
584 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
585
586 texDesc.fFormat = texDesc.fFormat;
587 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
588 texDesc.fStencilBits = desc.fStencilBits;
589 texDesc.fTextureID = desc.fPlatformTexture;
590 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
591 texDesc.fOwnsID = false;
592
593 params.invalidate(); // rather than do glGets.
594
595 return new GrGLTexture(this, texDesc, rtIDs, params);
596 } else {
597 GrGLIRect viewport;
598 viewport.fLeft = 0;
599 viewport.fBottom = 0;
600 viewport.fWidth = desc.fWidth;
601 viewport.fHeight = desc.fHeight;
602
603 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
604 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
605 viewport, NULL);
606 }
607}
608
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000609GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(
reed@google.comac10a2d2010-12-22 21:39:39 +0000610 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000611 int stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000612 bool isMultisampled,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000613 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000614 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000615 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
616 rtIDs.fStencilRenderbufferID = 0;
617 rtIDs.fMSColorRenderbufferID = 0;
618 rtIDs.fTexFBOID = 0;
619 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000620 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000621
622 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000623 viewport.fLeft = 0;
624 viewport.fBottom = 0;
625 viewport.fWidth = width;
626 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000627
twiz@google.com0f31ca72011-03-18 17:38:11 +0000628 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
629 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000630
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000631 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
632 isMultisampled, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000633}
634
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000635GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000636
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000637 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000638
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000639 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000640 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
641 rtIDs.fMSColorRenderbufferID = 0;
642 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000643
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000644 GrGLIRect viewport;
645 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000646 GrGLuint stencilBits;
647 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000648
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000649 GrGLint samples;
650 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
651
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000652 rtIDs.fOwnIDs = false;
653
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000654 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
655 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000656}
657
bsalomon@google.com5782d712011-01-21 21:03:59 +0000658///////////////////////////////////////////////////////////////////////////////
659
twiz@google.com0f31ca72011-03-18 17:38:11 +0000660static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000661
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000662struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000663 GrGLenum fEnum;
664 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000665 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000666};
667
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000668const StencilFormat* GrGLStencilFormats() {
669 // defines stencil formats from more to less preferred
670 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000671 {GR_GL_STENCIL_INDEX8, 8, false},
672 {GR_GL_STENCIL_INDEX16, 16, false},
673 {GR_GL_DEPTH24_STENCIL8, 8, true },
674 {GR_GL_STENCIL_INDEX4, 4, false},
675 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
676 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
677 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000678 };
679
680 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000681 {GR_GL_STENCIL_INDEX8, 8, false},
682 {GR_GL_DEPTH24_STENCIL8, 8, true },
683 {GR_GL_STENCIL_INDEX4, 4, false},
684 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000685 };
686
687 if (GR_GL_SUPPORT_DESKTOP) {
688 return desktopStencilFormats;
689 } else {
690 return esStencilFormats;
691 }
692}
693
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000694// good to set a break-point here to know when createTexture fails
695static GrTexture* return_null_texture() {
696// GrAssert(!"null texture");
697 return NULL;
698}
699
700#if GR_DEBUG
701static size_t as_size_t(int x) {
702 return x;
703}
704#endif
705
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000706GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000707 const void* srcData,
708 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000709
710#if GR_COLLECT_STATS
711 ++fStats.fTextureCreateCnt;
712#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000713
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000714 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000715
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000716 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000717 GR_GL_NEAREST,
718 GR_GL_CLAMP_TO_EDGE,
719 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000720 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000721
reed@google.comac10a2d2010-12-22 21:39:39 +0000722 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000723 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000724
725 glDesc.fContentWidth = desc.fWidth;
726 glDesc.fContentHeight = desc.fHeight;
727 glDesc.fAllocWidth = desc.fWidth;
728 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000729 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000730 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000731 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000732
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000733 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000734 if (!canBeTexture(desc.fFormat,
735 &internalFormat,
736 &glDesc.fUploadFormat,
737 &glDesc.fUploadType)) {
738 return return_null_texture();
739 }
740
741 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000742 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000743 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000744 GrPrintf("AA RT requested but not supported on this platform.");
745 }
746
747 GR_GL(GenTextures(1, &glDesc.fTextureID));
748 if (!glDesc.fTextureID) {
749 return return_null_texture();
750 }
751
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000752 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000753
reed@google.com5e762232011-04-04 18:15:49 +0000754 // in case we need a temporary, trimmed copy of the src pixels
755 GrAutoSMalloc<128 * 128> trimStorage;
756
reed@google.comac10a2d2010-12-22 21:39:39 +0000757 /*
758 * check if our srcData has extra bytes past each row. If so, we need
759 * to trim those off here, since GL doesn't let us pass the rowBytes as
760 * a parameter to glTexImage2D
761 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000762 if (GR_GL_SUPPORT_DESKTOP) {
763 if (srcData) {
764 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
765 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000766 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000767 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000768 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
769 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000770 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000771 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000772 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000773 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000774 for (uint32_t y = 0; y < desc.fHeight; y++) {
775 memcpy(dst, src, trimRowBytes);
776 src += rowBytes;
777 dst += trimRowBytes;
778 }
779 // now point srcData to our trimmed version
780 srcData = trimStorage.get();
781 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000782 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000783
reed@google.comac10a2d2010-12-22 21:39:39 +0000784 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000785 if (!this->npotRenderTargetSupport()) {
786 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
787 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
788 }
789
reed@google.comac10a2d2010-12-22 21:39:39 +0000790 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
791 glDesc.fAllocWidth);
792 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
793 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000794 } else if (!this->npotTextureSupport()) {
795 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
796 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000797 }
798
twiz@google.com0f31ca72011-03-18 17:38:11 +0000799 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
800 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
801 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000802 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000803 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
804 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000805 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000806 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
807 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000808 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000809 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
810 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000811 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000812
twiz@google.com0f31ca72011-03-18 17:38:11 +0000813 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000814 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000815 supports8BitPalette()) {
816 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
817 GrAssert(desc.fWidth == glDesc.fAllocWidth);
818 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000819 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000820 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000821 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000822 glDesc.fAllocWidth, glDesc.fAllocHeight,
823 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000824 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000825 } else {
826 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
827 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000828 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000829 glDesc.fAllocWidth, glDesc.fAllocHeight,
830 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000831 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000832 desc.fHeight, glDesc.fUploadFormat,
833 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000834 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000835
836 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
837 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
838 uint32_t maxTexels = extraW * extraH;
839 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
840 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
841
842 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
843
844 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
845 if (extraH) {
846 uint8_t* lastRowStart = (uint8_t*) srcData +
847 (desc.fHeight - 1) * rowSize;
848 uint8_t* extraRowStart = (uint8_t*)texels.get();
849
850 for (uint32_t i = 0; i < extraH; ++i) {
851 memcpy(extraRowStart, lastRowStart, rowSize);
852 extraRowStart += rowSize;
853 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000854 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000855 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
856 texels.get()));
857 }
858 if (extraW) {
859 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
860 uint8_t* extraTexel = (uint8_t*)texels.get();
861 for (uint32_t j = 0; j < desc.fHeight; ++j) {
862 for (uint32_t i = 0; i < extraW; ++i) {
863 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
864 extraTexel += glDesc.fUploadByteCount;
865 }
866 edgeTexel += rowSize;
867 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000868 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000869 desc.fHeight, glDesc.fUploadFormat,
870 glDesc.fUploadType, texels.get()));
871 }
872 if (extraW && extraH) {
873 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
874 - glDesc.fUploadByteCount;
875 uint8_t* extraTexel = (uint8_t*)texels.get();
876 for (uint32_t i = 0; i < extraW*extraH; ++i) {
877 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
878 extraTexel += glDesc.fUploadByteCount;
879 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000880 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000881 extraW, extraH, glDesc.fUploadFormat,
882 glDesc.fUploadType, texels.get()));
883 }
884
885 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000886 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000887 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
888 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000889 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000890 }
891 }
892
893 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
894
895 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
896 rtIDs.fStencilRenderbufferID = 0;
897 rtIDs.fMSColorRenderbufferID = 0;
898 rtIDs.fRTFBOID = 0;
899 rtIDs.fTexFBOID = 0;
900 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000901 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000902
903 if (renderTarget) {
904#if GR_COLLECT_STATS
905 ++fStats.fRenderTargetCreateCnt;
906#endif
907 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000908 GrGLenum status;
909 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000910
911 // If need have both RT flag and srcData we have
912 // to invert the data before uploading because FBO
913 // will be rendered bottom up
914 GrAssert(NULL == srcData);
915 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
916
twiz@google.com59a190b2011-03-14 21:23:01 +0000917 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000918 GrAssert(rtIDs.fTexFBOID);
919
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000920 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000921 // to one and then resolve to the texture bound to the other.
922 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000923 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000924 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000925 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000926 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
927 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000928 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000929 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000930 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
931 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000932 return return_null_texture();
933 }
934 } else {
935 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
936 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000937 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000938 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000939 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000940 }
941
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000942 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000943 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000944 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000945 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000946
twiz@google.com0f31ca72011-03-18 17:38:11 +0000947 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000948
949 const StencilFormat* stencilFormats = GrGLStencilFormats();
950 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000951 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000952 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000953 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000954 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000955 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000956 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000957 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000958 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000959 glDesc.fAllocWidth,
960 glDesc.fAllocHeight));
961 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000962 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000963 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000964 glDesc.fAllocWidth,
965 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000966 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000967 err = GrGLGetGLInterface()->fGetError();
968 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000969 continue;
970 }
971 }
972 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
973 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000974 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000975 rtIDs.fMSColorRenderbufferID));
976 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000977 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000978 samples,
979 msColorRenderbufferFormat,
980 glDesc.fAllocWidth,
981 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000982 err = GrGLGetGLInterface()->fGetError();
983 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000984 continue;
985 }
986 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000987 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000988
989#if GR_COLLECT_STATS
990 ++fStats.fRenderTargetChngCnt;
991#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000992 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
993 GR_GL_COLOR_ATTACHMENT0,
994 GR_GL_TEXTURE_2D,
995 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000996 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000997 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
998 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000999 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1000 status, desc.fWidth, desc.fHeight);
1001 continue;
1002 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001003 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001004 #if GR_COLLECT_STATS
1005 ++fStats.fRenderTargetChngCnt;
1006 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001007 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1008 GR_GL_COLOR_ATTACHMENT0,
1009 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001010 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001011
1012 }
1013 if (rtIDs.fStencilRenderbufferID) {
1014 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001015 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1016 GR_GL_STENCIL_ATTACHMENT,
1017 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001018 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001019 // if it is a packed format bind to depth also, otherwise
1020 // we may get an unsupported fbo completeness result
1021 if (stencilFormats[i].fPacked) {
1022 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1023 GR_GL_DEPTH_ATTACHMENT,
1024 GR_GL_RENDERBUFFER,
1025 rtIDs.fStencilRenderbufferID));
1026 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001027 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001028 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001029
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001030 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001031 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1032 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001033 // undo the depth bind
1034 if (rtIDs.fStencilRenderbufferID &&
1035 stencilFormats[i].fPacked) {
1036 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1037 GR_GL_DEPTH_ATTACHMENT,
1038 GR_GL_RENDERBUFFER,
1039 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001040 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001041 continue;
1042 }
1043 // we're successful!
1044 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001045 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001046 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001047 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001048 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001049 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001050 }
1051 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001052 break;
1053 }
1054 if (failed) {
1055 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001056 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001057 }
1058 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001059 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001060 }
1061 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001062 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001063 }
1064 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001065 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001066 }
1067 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1068 return return_null_texture();
1069 }
1070 }
1071#ifdef TRACE_TEXTURE_CREATION
1072 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1073 tex->fTextureID, width, height, tex->fUploadByteCount);
1074#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001075 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001076
1077 if (0 != rtIDs.fTexFBOID) {
1078 GrRenderTarget* rt = tex->asRenderTarget();
1079 // We've messed with FBO state but may not have set the correct viewport
1080 // so just dirty the rendertarget state to force a resend.
1081 fHWDrawState.fRenderTarget = NULL;
1082
1083 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001084 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001085 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1086 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001087 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 fCurrDrawState.fRenderTarget = rtSave;
1089 }
1090 }
1091 return tex;
1092}
1093
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001094GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001095 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001096 GR_GL(GenBuffers(1, &id));
1097 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001098 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001099 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001100 GrGLClearErr();
1101 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001102 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1103 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1104 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001105 GR_GL(DeleteBuffers(1, &id));
1106 // deleting bound buffer does implicit bind to 0
1107 fHWGeometryState.fVertexBuffer = NULL;
1108 return NULL;
1109 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001110 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001111 size, dynamic);
1112 fHWGeometryState.fVertexBuffer = vertexBuffer;
1113 return vertexBuffer;
1114 }
1115 return NULL;
1116}
1117
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001118GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001119 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001120 GR_GL(GenBuffers(1, &id));
1121 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001122 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001123 GrGLClearErr();
1124 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001125 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1126 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1127 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001128 GR_GL(DeleteBuffers(1, &id));
1129 // deleting bound buffer does implicit bind to 0
1130 fHWGeometryState.fIndexBuffer = NULL;
1131 return NULL;
1132 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001133 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001134 size, dynamic);
1135 fHWGeometryState.fIndexBuffer = indexBuffer;
1136 return indexBuffer;
1137 }
1138 return NULL;
1139}
1140
reed@google.comac10a2d2010-12-22 21:39:39 +00001141void GrGpuGL::flushScissor(const GrIRect* rect) {
1142 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001143 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001144 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001145
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001146 GrGLIRect scissor;
1147 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001148 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001149 rect->width(), rect->height());
1150 if (scissor.contains(vp)) {
1151 rect = NULL;
1152 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001153 }
1154
1155 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001157 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001158 fHWBounds.fScissorRect = scissor;
1159 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001160 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001161 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001162 fHWBounds.fScissorEnabled = true;
1163 }
1164 } else {
1165 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001166 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001167 fHWBounds.fScissorEnabled = false;
1168 }
1169 }
1170}
1171
bsalomon@google.com398109c2011-04-14 18:40:27 +00001172void GrGpuGL::onClear(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001173 if (NULL == fCurrDrawState.fRenderTarget) {
1174 return;
1175 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001176 flushRenderTarget();
1177 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001178 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001179 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001180 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001181 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001182 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001183 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1184 GrColorUnpackG(color)/255.f,
1185 GrColorUnpackB(color)/255.f,
1186 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001187 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001188}
1189
bsalomon@google.com398109c2011-04-14 18:40:27 +00001190void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001191 if (NULL == fCurrDrawState.fRenderTarget) {
1192 return;
1193 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001194 flushRenderTarget();
1195 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001196 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001197 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001198 }
1199 GR_GL(StencilMask(mask));
1200 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001201 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001202 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001203}
1204
bsalomon@google.com398109c2011-04-14 18:40:27 +00001205void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001206 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001207#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001208 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001209 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001210 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001211#else
1212 // we could just clear the clip bit but when we go through
1213 // angle a partial stencil mask will cause clears to be
1214 // turned into draws. Our contract on GrDrawTarget says that
1215 // changing the clip between stencil passes may or may not
1216 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001217 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001218#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001219 flushRenderTarget();
1220 flushScissor(&rect);
1221 GR_GL(StencilMask(clipStencilMask));
1222 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001223 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001224 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001225}
1226
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001227void GrGpuGL::onForceRenderTargetFlush() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001228 flushRenderTarget();
1229}
1230
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001231bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1232 int left, int top, int width, int height,
1233 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001234 GrGLenum internalFormat; // we don't use this for glReadPixels
1235 GrGLenum format;
1236 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001237 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1238 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001239 }
1240 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1241 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1242 switch (tgt->getResolveType()) {
1243 case GrGLRenderTarget::kCantResolve_ResolveType:
1244 return false;
1245 case GrGLRenderTarget::kAutoResolves_ResolveType:
1246 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1247 fCurrDrawState.fRenderTarget = target;
1248 flushRenderTarget();
1249 break;
1250 case GrGLRenderTarget::kCanResolve_ResolveType:
1251 resolveRenderTarget(tgt);
1252 // we don't track the state of the READ FBO ID.
1253 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1254 break;
1255 default:
1256 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001257 }
1258
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001259 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001260
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001261 // the read rect is viewport-relative
1262 GrGLIRect readRect;
1263 readRect.setRelativeTo(glvp, left, top, width, height);
1264 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001265 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001266 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001267
1268 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1269 // API presents top-to-bottom
1270 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001271 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001272 GrAutoMalloc rowStorage(stride);
1273 void* tmp = rowStorage.get();
1274
1275 const int halfY = height >> 1;
1276 char* top = reinterpret_cast<char*>(buffer);
1277 char* bottom = top + (height - 1) * stride;
1278 for (int y = 0; y < halfY; y++) {
1279 memcpy(tmp, top, stride);
1280 memcpy(top, bottom, stride);
1281 memcpy(bottom, tmp, stride);
1282 top += stride;
1283 bottom -= stride;
1284 }
1285 }
1286 return true;
1287}
1288
1289void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001290
1291 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1292
reed@google.comac10a2d2010-12-22 21:39:39 +00001293 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1294 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001295 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001296 #if GR_COLLECT_STATS
1297 ++fStats.fRenderTargetChngCnt;
1298 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001299 rt->flagAsNeedingResolve();
reed@google.comac10a2d2010-12-22 21:39:39 +00001300 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001301 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1302 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001303 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1304 }
1305 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001306 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001307 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001308 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001309 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001310 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001311 fHWBounds.fViewportRect = vp;
1312 }
1313 }
1314}
1315
twiz@google.com0f31ca72011-03-18 17:38:11 +00001316GrGLenum gPrimitiveType2GLMode[] = {
1317 GR_GL_TRIANGLES,
1318 GR_GL_TRIANGLE_STRIP,
1319 GR_GL_TRIANGLE_FAN,
1320 GR_GL_POINTS,
1321 GR_GL_LINES,
1322 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001323};
1324
bsalomon@google.comd302f142011-03-03 13:54:13 +00001325#define SWAP_PER_DRAW 0
1326
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001327#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001328 #if GR_MAC_BUILD
1329 #include <AGL/agl.h>
1330 #elif GR_WIN32_BUILD
1331 void SwapBuf() {
1332 DWORD procID = GetCurrentProcessId();
1333 HWND hwnd = GetTopWindow(GetDesktopWindow());
1334 while(hwnd) {
1335 DWORD wndProcID = 0;
1336 GetWindowThreadProcessId(hwnd, &wndProcID);
1337 if(wndProcID == procID) {
1338 SwapBuffers(GetDC(hwnd));
1339 }
1340 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1341 }
1342 }
1343 #endif
1344#endif
1345
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001346void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1347 uint32_t startVertex,
1348 uint32_t startIndex,
1349 uint32_t vertexCount,
1350 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001351 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1352
twiz@google.com0f31ca72011-03-18 17:38:11 +00001353 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001354
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001355 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1356 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1357
1358 // our setupGeometry better have adjusted this to zero since
1359 // DrawElements always draws from the begining of the arrays for idx 0.
1360 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001361
1362 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001363 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001364#if SWAP_PER_DRAW
1365 glFlush();
1366 #if GR_MAC_BUILD
1367 aglSwapBuffers(aglGetCurrentContext());
1368 int set_a_break_pt_here = 9;
1369 aglSwapBuffers(aglGetCurrentContext());
1370 #elif GR_WIN32_BUILD
1371 SwapBuf();
1372 int set_a_break_pt_here = 9;
1373 SwapBuf();
1374 #endif
1375#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001376}
1377
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001378void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1379 uint32_t startVertex,
1380 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001381 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1382
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001383 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1384
1385 // our setupGeometry better have adjusted this to zero.
1386 // DrawElements doesn't take an offset so we always adjus the startVertex.
1387 GrAssert(0 == startVertex);
1388
1389 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1390 // account for startVertex in the DrawElements case. So we always
1391 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001392 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001393#if SWAP_PER_DRAW
1394 glFlush();
1395 #if GR_MAC_BUILD
1396 aglSwapBuffers(aglGetCurrentContext());
1397 int set_a_break_pt_here = 9;
1398 aglSwapBuffers(aglGetCurrentContext());
1399 #elif GR_WIN32_BUILD
1400 SwapBuf();
1401 int set_a_break_pt_here = 9;
1402 SwapBuf();
1403 #endif
1404#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001405}
1406
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001407void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001408
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001409 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001410 GrAssert(kNone_MSFBO != fMSFBOType);
1411 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001412 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001413 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001414 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001415 rt->textureFBOID()));
1416 #if GR_COLLECT_STATS
1417 ++fStats.fRenderTargetChngCnt;
1418 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001419 // make sure we go through flushRenderTarget() since we've modified
1420 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001421 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001422 const GrGLIRect& vp = rt->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001423
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001424 if (kAppleES_MSFBO == fMSFBOType) {
1425 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001426 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001427 GR_GL(Scissor(vp.fLeft, vp.fBottom,
1428 vp.fWidth, vp.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001429 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001430 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001431 fHWBounds.fScissorEnabled = true;
1432 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001433 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001434 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001435 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1436 flushScissor(NULL);
1437 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001438 int right = vp.fLeft + vp.fWidth;
1439 int top = vp.fBottom + vp.fHeight;
1440 GR_GL(BlitFramebuffer(vp.fLeft, vp.fBottom, right, top,
1441 vp.fLeft, vp.fBottom, right, top,
1442 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001443 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001444 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001445 }
1446}
1447
twiz@google.com0f31ca72011-03-18 17:38:11 +00001448static const GrGLenum grToGLStencilFunc[] = {
1449 GR_GL_ALWAYS, // kAlways_StencilFunc
1450 GR_GL_NEVER, // kNever_StencilFunc
1451 GR_GL_GREATER, // kGreater_StencilFunc
1452 GR_GL_GEQUAL, // kGEqual_StencilFunc
1453 GR_GL_LESS, // kLess_StencilFunc
1454 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1455 GR_GL_EQUAL, // kEqual_StencilFunc,
1456 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001457};
1458GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1459GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1460GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1461GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1462GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1463GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1464GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1465GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1466GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1467
twiz@google.com0f31ca72011-03-18 17:38:11 +00001468static const GrGLenum grToGLStencilOp[] = {
1469 GR_GL_KEEP, // kKeep_StencilOp
1470 GR_GL_REPLACE, // kReplace_StencilOp
1471 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1472 GR_GL_INCR, // kIncClamp_StencilOp
1473 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1474 GR_GL_DECR, // kDecClamp_StencilOp
1475 GR_GL_ZERO, // kZero_StencilOp
1476 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001477};
1478GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1479GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1480GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1481GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1482GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1483GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1484GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1485GR_STATIC_ASSERT(6 == kZero_StencilOp);
1486GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1487
reed@google.comac10a2d2010-12-22 21:39:39 +00001488void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001489 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001490
1491 // use stencil for clipping if clipping is enabled and the clip
1492 // has been written into the stencil.
1493 bool stencilClip = fClipState.fClipInStencil &&
1494 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001495 bool stencilChange = fHWStencilClip != stencilClip ||
1496 fHWDrawState.fStencilSettings != *settings ||
1497 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1498 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001499
1500 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001501
bsalomon@google.comd302f142011-03-03 13:54:13 +00001502 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1503 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001504
bsalomon@google.comd302f142011-03-03 13:54:13 +00001505 if (settings->isDisabled()) {
1506 if (stencilClip) {
1507 settings = &gClipStencilSettings;
1508 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001509 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001510
1511 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001512 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001513 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001514 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001515 #if GR_DEBUG
1516 if (!fStencilWrapOpsSupport) {
1517 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1518 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1519 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1520 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1521 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1522 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1523 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1524 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1525 }
1526 #endif
1527 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1528 GrAssert(stencilBits ||
1529 (GrStencilSettings::gDisabled ==
1530 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001531 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1532 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001533
1534 unsigned int frontRef = settings->fFrontFuncRef;
1535 unsigned int frontMask = settings->fFrontFuncMask;
1536 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001537 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001538
1539 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1540
1541 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1542 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1543 } else {
1544 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1545
1546 ConvertStencilFuncAndMask(settings->fFrontFunc,
1547 stencilClip,
1548 clipStencilMask,
1549 userStencilMask,
1550 &frontRef,
1551 &frontMask);
1552 frontWriteMask &= userStencilMask;
1553 }
1554 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001555 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001556 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001557 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001558 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001559 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001560 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001561 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001562 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001563 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001564
1565 unsigned int backRef = settings->fBackFuncRef;
1566 unsigned int backMask = settings->fBackFuncMask;
1567 unsigned int backWriteMask = settings->fBackWriteMask;
1568
1569
1570 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1571 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1572 backFunc = grToGLStencilFunc[settings->fBackFunc];
1573 } else {
1574 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1575 ConvertStencilFuncAndMask(settings->fBackFunc,
1576 stencilClip,
1577 clipStencilMask,
1578 userStencilMask,
1579 &backRef,
1580 &backMask);
1581 backWriteMask &= userStencilMask;
1582 }
1583
twiz@google.com0f31ca72011-03-18 17:38:11 +00001584 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1585 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1586 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1587 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1588 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001589 grToGLStencilOp[settings->fFrontPassOp],
1590 grToGLStencilOp[settings->fFrontPassOp]));
1591
twiz@google.com0f31ca72011-03-18 17:38:11 +00001592 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001593 grToGLStencilOp[settings->fBackPassOp],
1594 grToGLStencilOp[settings->fBackPassOp]));
1595 } else {
1596 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1597 GR_GL(StencilMask(frontWriteMask));
1598 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1599 grToGLStencilOp[settings->fFrontPassOp],
1600 grToGLStencilOp[settings->fFrontPassOp]));
1601 }
1602 }
1603 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001604 fHWStencilClip = stencilClip;
1605 }
1606}
1607
bsalomon@google.com0650e812011-04-08 18:07:53 +00001608bool GrGpuGL::useSmoothLines() {
1609 // there is a conflict between using smooth lines and our use of
1610 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1611 // but not in a premul-alpha way. So we only use them when our alpha
1612 // is 0xff.
1613
1614 // TODO: write a smarter line frag shader.
1615
1616 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1617 canDisableBlend();
1618}
1619
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001620void GrGpuGL::flushAAState(GrPrimitiveType type) {
1621 if (GR_GL_SUPPORT_DESKTOP) {
1622 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1623 // smooth lines.
1624
1625 // we prefer smooth lines over multisampled lines
1626 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001627 if (GrIsPrimTypeLines(type)) {
1628 bool smooth = useSmoothLines();
1629 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001630 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1631 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001632 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001633 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1634 fHWAAState.fSmoothLineEnabled = false;
1635 }
1636 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1637 fHWAAState.fMSAAEnabled) {
1638 GR_GL(Disable(GR_GL_MULTISAMPLE));
1639 fHWAAState.fMSAAEnabled = false;
1640 }
1641 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1642 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1643 fHWAAState.fMSAAEnabled) {
1644 if (fHWAAState.fMSAAEnabled) {
1645 GR_GL(Disable(GR_GL_MULTISAMPLE));
1646 fHWAAState.fMSAAEnabled = false;
1647 } else {
1648 GR_GL(Enable(GR_GL_MULTISAMPLE));
1649 fHWAAState.fMSAAEnabled = true;
1650 }
1651 }
1652 }
1653}
1654
bsalomon@google.com0650e812011-04-08 18:07:53 +00001655void GrGpuGL::flushBlend(GrPrimitiveType type) {
1656 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1657 if (fHWBlendDisabled) {
1658 GR_GL(Enable(GR_GL_BLEND));
1659 fHWBlendDisabled = false;
1660 }
1661 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1662 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1663 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1664 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1665 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1666 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1667 }
1668 } else {
1669 bool blendOff = canDisableBlend();
1670 if (fHWBlendDisabled != blendOff) {
1671 if (blendOff) {
1672 GR_GL(Disable(GR_GL_BLEND));
1673 } else {
1674 GR_GL(Enable(GR_GL_BLEND));
1675 }
1676 fHWBlendDisabled = blendOff;
1677 }
1678 if (!blendOff) {
1679 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1680 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1681 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1682 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1683 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1684 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1685 }
1686 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1687 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1688 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1689
1690 float c[] = {
1691 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1692 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1693 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1694 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1695 };
1696 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1697 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1698 }
1699 }
1700 }
1701}
1702
bsalomon@google.comffca4002011-02-22 20:34:01 +00001703bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001704
1705 // GrGpu::setupClipAndFlushState should have already checked this
1706 // and bailed if not true.
1707 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001708
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001709 for (int s = 0; s < kNumStages; ++s) {
1710 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001711
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001712 // bind texture and set sampler state
1713 if (usingTexture) {
1714 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001715
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001716 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001717 // if we created a rt/tex and rendered to it without using a
1718 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001719 // the last bound texture, but it needs resolving. So keep this
1720 // out of the "last != next" check.
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001721 GrGLRenderTarget* texRT =
1722 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1723 if (NULL != texRT) {
1724 resolveRenderTarget(texRT);
1725 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001726
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001727 if (fHWDrawState.fTextures[s] != nextTexture) {
1728 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001729 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001730 #if GR_COLLECT_STATS
1731 ++fStats.fTextureChngCnt;
1732 #endif
1733 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1734 fHWDrawState.fTextures[s] = nextTexture;
1735 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001736
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001737 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001738 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001739 nextTexture->getTexParams();
1740 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001741
twiz@google.com0f31ca72011-03-18 17:38:11 +00001742 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1743 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001744 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001745 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001746 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001747 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001748
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001749 if (newTexParams.fFilter != oldTexParams.fFilter) {
1750 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001751 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1752 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001753 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001754 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1755 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001756 newTexParams.fFilter));
1757 }
1758 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1759 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001760 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1761 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001762 newTexParams.fWrapS));
1763 }
1764 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1765 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001766 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1767 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001768 newTexParams.fWrapT));
1769 }
1770 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001771
1772 // The texture matrix has to compensate for texture width/height
1773 // and NPOT-embedded-in-POT
1774 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001775 } else {
1776 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001777 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001778 }
1779 }
1780 }
1781
1782 flushRenderTarget();
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001783 flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001784 flushBlend(type);
1785
reed@google.comac10a2d2010-12-22 21:39:39 +00001786 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1787 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1788 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001789 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001790 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001791 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001792 }
1793 }
1794
bsalomon@google.comd302f142011-03-03 13:54:13 +00001795 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1796 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001797 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001798 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001799 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001800 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001801 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001802 }
1803 GR_GL(ColorMask(mask, mask, mask, mask));
1804 }
1805
bsalomon@google.comd302f142011-03-03 13:54:13 +00001806 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1807 switch (fCurrDrawState.fDrawFace) {
1808 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001809 GR_GL(Enable(GR_GL_CULL_FACE));
1810 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001811 break;
1812 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001813 GR_GL(Enable(GR_GL_CULL_FACE));
1814 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001815 break;
1816 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001817 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001818 break;
1819 default:
1820 GrCrash("Unknown draw face.");
1821 }
1822 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1823 }
1824
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001825#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001826 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001827 for (int s = 0; s < kNumStages; ++s) {
1828 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1829 NULL == fCurrDrawState.fRenderTarget ||
1830 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001831 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001832 fCurrDrawState.fRenderTarget);
1833 }
1834#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001835
reed@google.comac10a2d2010-12-22 21:39:39 +00001836 flushStencil();
1837
bsalomon@google.comd302f142011-03-03 13:54:13 +00001838 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001839 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001840 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001841}
1842
1843void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001844 if (fHWGeometryState.fVertexBuffer != buffer) {
1845 fHWGeometryState.fArrayPtrsDirty = true;
1846 fHWGeometryState.fVertexBuffer = buffer;
1847 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001848}
1849
1850void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001851 if (fHWGeometryState.fVertexBuffer == buffer) {
1852 // deleting bound buffer does implied bind to 0
1853 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001854 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001855 }
1856}
1857
1858void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1859 fGeometrySrc.fIndexBuffer = buffer;
1860}
1861
1862void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001863 if (fHWGeometryState.fIndexBuffer == buffer) {
1864 // deleting bound buffer does implied bind to 0
1865 fHWGeometryState.fIndexBuffer = NULL;
1866 }
1867}
1868
reed@google.comac10a2d2010-12-22 21:39:39 +00001869void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1870 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001871 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001872 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001873 }
1874 if (fHWDrawState.fRenderTarget == renderTarget) {
1875 fHWDrawState.fRenderTarget = NULL;
1876 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001877}
1878
1879void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001880 for (int s = 0; s < kNumStages; ++s) {
1881 if (fCurrDrawState.fTextures[s] == texture) {
1882 fCurrDrawState.fTextures[s] = NULL;
1883 }
1884 if (fHWDrawState.fTextures[s] == texture) {
1885 // deleting bound texture does implied bind to 0
1886 fHWDrawState.fTextures[s] = NULL;
1887 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001888 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001889}
1890
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001891bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001892 GrGLenum* internalFormat,
1893 GrGLenum* format,
1894 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001895 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001896 case kRGBA_8888_GrPixelConfig:
1897 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001898 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001899 if (GR_GL_SUPPORT_ES) {
1900 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1901 // format for a BGRA is BGRA not RGBA (as on desktop)
1902 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1903 } else {
1904 *internalFormat = GR_GL_RGBA;
1905 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001906 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001907 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001908 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001909 *format = GR_GL_RGB;
1910 *internalFormat = GR_GL_RGB;
1911 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001912 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001913 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001914 *format = GR_GL_RGBA;
1915 *internalFormat = GR_GL_RGBA;
1916 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001917 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001918 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001919 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001920 *format = GR_GL_PALETTE8_RGBA8;
1921 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001922 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001923 } else {
1924 return false;
1925 }
1926 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001927 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001928 *format = GR_GL_ALPHA;
1929 *internalFormat = GR_GL_ALPHA;
1930 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001931 break;
1932 default:
1933 return false;
1934 }
1935 return true;
1936}
1937
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001938void GrGpuGL::setTextureUnit(int unit) {
1939 GrAssert(unit >= 0 && unit < kNumStages);
1940 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001941 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001942 fActiveTextureUnitIdx = unit;
1943 }
1944}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001945
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001946void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001947 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1948 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001949 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1950 }
1951}
1952
reed@google.comac10a2d2010-12-22 21:39:39 +00001953/* On ES the internalFormat and format must match for TexImage and we use
1954 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1955 decide the internalFormat. However, on ES internalFormat for
1956 RenderBufferStorage* has to be a specific format (not a base format like
1957 GL_RGBA).
1958 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001959bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001960 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001961 case kRGBA_8888_GrPixelConfig:
1962 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001963 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001964 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001965 return true;
1966 } else {
1967 return false;
1968 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001969 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001970 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1971 // with FBO extension desktop GL has
1972 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001973 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001974 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001975 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001976 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001977 return true;
1978 default:
1979 return false;
1980 }
1981}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001982
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001983void GrGpuGL::resetDirtyFlags() {
1984 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1985}
1986
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001987void GrGpuGL::setBuffers(bool indexed,
1988 int* extraVertexOffset,
1989 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001990
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001991 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001992
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001993 GrGLVertexBuffer* vbuf;
1994 switch (fGeometrySrc.fVertexSrc) {
1995 case kBuffer_GeometrySrcType:
1996 *extraVertexOffset = 0;
1997 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1998 break;
1999 case kArray_GeometrySrcType:
2000 case kReserved_GeometrySrcType:
2001 finalizeReservedVertices();
2002 *extraVertexOffset = fCurrPoolStartVertex;
2003 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2004 break;
2005 default:
2006 vbuf = NULL; // suppress warning
2007 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002008 }
2009
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002010 GrAssert(NULL != vbuf);
2011 GrAssert(!vbuf->isLocked());
2012 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002013 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002014 fHWGeometryState.fArrayPtrsDirty = true;
2015 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002016 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002017
2018 if (indexed) {
2019 GrAssert(NULL != extraIndexOffset);
2020
2021 GrGLIndexBuffer* ibuf;
2022 switch (fGeometrySrc.fIndexSrc) {
2023 case kBuffer_GeometrySrcType:
2024 *extraIndexOffset = 0;
2025 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2026 break;
2027 case kArray_GeometrySrcType:
2028 case kReserved_GeometrySrcType:
2029 finalizeReservedIndices();
2030 *extraIndexOffset = fCurrPoolStartIndex;
2031 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2032 break;
2033 default:
2034 ibuf = NULL; // suppress warning
2035 GrCrash("Unknown geometry src type!");
2036 }
2037
2038 GrAssert(NULL != ibuf);
2039 GrAssert(!ibuf->isLocked());
2040 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002041 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002042 fHWGeometryState.fIndexBuffer = ibuf;
2043 }
2044 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002045}