blob: 0ea83a80e1807c43164d930c475181d1c8d3b0ab [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
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000533 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000534
twiz@google.com0f31ca72011-03-18 17:38:11 +0000535 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000536 fHWDrawState.fRenderTarget = NULL;
537}
538
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000539GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
540
541 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
542 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
543 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
544 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
545
546 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
547 if (isRenderTarget) {
548 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
549 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
550 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
551 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
552 } else {
553 GrAssert(!isTexture); // this should have been filtered by GrContext
554 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
555 }
556 } else {
557 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
558 }
559 // we don't know what the RB ids are without glGets and we don't care
560 // since we aren't responsible for deleting them.
561 rtIDs.fStencilRenderbufferID = 0;
562 rtIDs.fMSColorRenderbufferID = 0;
563
564 rtIDs.fOwnIDs = false;
565 } else {
566 rtIDs.reset();
567 }
568
569 if (isTexture) {
570 GrGLTexture::GLTextureDesc texDesc;
571 GrGLenum dontCare;
572 if (!canBeTexture(desc.fConfig, &dontCare,
573 &texDesc.fUploadFormat,
574 &texDesc.fUploadType)) {
575 return NULL;
576 }
577
578 GrGLTexture::TexParams params;
579
580 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
581 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
582
583 texDesc.fFormat = texDesc.fFormat;
584 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
585 texDesc.fStencilBits = desc.fStencilBits;
586 texDesc.fTextureID = desc.fPlatformTexture;
587 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
588 texDesc.fOwnsID = false;
589
590 params.invalidate(); // rather than do glGets.
591
592 return new GrGLTexture(this, texDesc, rtIDs, params);
593 } else {
594 GrGLIRect viewport;
595 viewport.fLeft = 0;
596 viewport.fBottom = 0;
597 viewport.fWidth = desc.fWidth;
598 viewport.fHeight = desc.fHeight;
599
600 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
601 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
602 viewport, NULL);
603 }
604}
605
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000606GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(
reed@google.comac10a2d2010-12-22 21:39:39 +0000607 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000608 int stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000609 bool isMultisampled,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000610 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000611 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000612 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
613 rtIDs.fStencilRenderbufferID = 0;
614 rtIDs.fMSColorRenderbufferID = 0;
615 rtIDs.fTexFBOID = 0;
616 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000617 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000618
619 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000620 viewport.fLeft = 0;
621 viewport.fBottom = 0;
622 viewport.fWidth = width;
623 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000624
twiz@google.com0f31ca72011-03-18 17:38:11 +0000625 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
626 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000627
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000628 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
629 isMultisampled, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000630}
631
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000632GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000633
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000634 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000635
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000636 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000637 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
638 rtIDs.fMSColorRenderbufferID = 0;
639 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000640
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000641 GrGLIRect viewport;
642 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000643 GrGLuint stencilBits;
644 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000645
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000646 GrGLint samples;
647 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
648
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000649 rtIDs.fOwnIDs = false;
650
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000651 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
652 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000653}
654
bsalomon@google.com5782d712011-01-21 21:03:59 +0000655///////////////////////////////////////////////////////////////////////////////
656
twiz@google.com0f31ca72011-03-18 17:38:11 +0000657static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000658
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000659struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000660 GrGLenum fEnum;
661 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000662 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000663};
664
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000665const StencilFormat* GrGLStencilFormats() {
666 // defines stencil formats from more to less preferred
667 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000668 {GR_GL_STENCIL_INDEX8, 8, false},
669 {GR_GL_STENCIL_INDEX16, 16, false},
670 {GR_GL_DEPTH24_STENCIL8, 8, true },
671 {GR_GL_STENCIL_INDEX4, 4, false},
672 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
673 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
674 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000675 };
676
677 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000678 {GR_GL_STENCIL_INDEX8, 8, false},
679 {GR_GL_DEPTH24_STENCIL8, 8, true },
680 {GR_GL_STENCIL_INDEX4, 4, false},
681 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000682 };
683
684 if (GR_GL_SUPPORT_DESKTOP) {
685 return desktopStencilFormats;
686 } else {
687 return esStencilFormats;
688 }
689}
690
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000691// good to set a break-point here to know when createTexture fails
692static GrTexture* return_null_texture() {
693// GrAssert(!"null texture");
694 return NULL;
695}
696
697#if GR_DEBUG
698static size_t as_size_t(int x) {
699 return x;
700}
701#endif
702
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000703GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000704 const void* srcData,
705 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000706
707#if GR_COLLECT_STATS
708 ++fStats.fTextureCreateCnt;
709#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000710
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000711 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000712
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000713 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000714 GR_GL_NEAREST,
715 GR_GL_CLAMP_TO_EDGE,
716 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000717 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000718
reed@google.comac10a2d2010-12-22 21:39:39 +0000719 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000720 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000721
722 glDesc.fContentWidth = desc.fWidth;
723 glDesc.fContentHeight = desc.fHeight;
724 glDesc.fAllocWidth = desc.fWidth;
725 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000726 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000727 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000728 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000729
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000730 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000731 if (!canBeTexture(desc.fFormat,
732 &internalFormat,
733 &glDesc.fUploadFormat,
734 &glDesc.fUploadType)) {
735 return return_null_texture();
736 }
737
738 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000739 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000740 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000741 GrPrintf("AA RT requested but not supported on this platform.");
742 }
743
744 GR_GL(GenTextures(1, &glDesc.fTextureID));
745 if (!glDesc.fTextureID) {
746 return return_null_texture();
747 }
748
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000749 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000750
reed@google.com5e762232011-04-04 18:15:49 +0000751 // in case we need a temporary, trimmed copy of the src pixels
752 GrAutoSMalloc<128 * 128> trimStorage;
753
reed@google.comac10a2d2010-12-22 21:39:39 +0000754 /*
755 * check if our srcData has extra bytes past each row. If so, we need
756 * to trim those off here, since GL doesn't let us pass the rowBytes as
757 * a parameter to glTexImage2D
758 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000759 if (GR_GL_SUPPORT_DESKTOP) {
760 if (srcData) {
761 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
762 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000763 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000764 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000765 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
766 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000767 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000768 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000769 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000770 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000771 for (uint32_t y = 0; y < desc.fHeight; y++) {
772 memcpy(dst, src, trimRowBytes);
773 src += rowBytes;
774 dst += trimRowBytes;
775 }
776 // now point srcData to our trimmed version
777 srcData = trimStorage.get();
778 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000779 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000780
reed@google.comac10a2d2010-12-22 21:39:39 +0000781 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000782 if (!this->npotRenderTargetSupport()) {
783 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
784 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
785 }
786
reed@google.comac10a2d2010-12-22 21:39:39 +0000787 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
788 glDesc.fAllocWidth);
789 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
790 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000791 } else if (!this->npotTextureSupport()) {
792 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
793 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000794 }
795
twiz@google.com0f31ca72011-03-18 17:38:11 +0000796 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
797 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
798 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000799 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000800 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
801 GR_GL_TEXTURE_MIN_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_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000805 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000806 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
807 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000808 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000809
twiz@google.com0f31ca72011-03-18 17:38:11 +0000810 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000811 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000812 supports8BitPalette()) {
813 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
814 GrAssert(desc.fWidth == glDesc.fAllocWidth);
815 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000816 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000817 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000818 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000819 glDesc.fAllocWidth, glDesc.fAllocHeight,
820 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000821 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000822 } else {
823 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
824 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000825 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000826 glDesc.fAllocWidth, glDesc.fAllocHeight,
827 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000828 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000829 desc.fHeight, glDesc.fUploadFormat,
830 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000831 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000832
833 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
834 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
835 uint32_t maxTexels = extraW * extraH;
836 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
837 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
838
839 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
840
841 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
842 if (extraH) {
843 uint8_t* lastRowStart = (uint8_t*) srcData +
844 (desc.fHeight - 1) * rowSize;
845 uint8_t* extraRowStart = (uint8_t*)texels.get();
846
847 for (uint32_t i = 0; i < extraH; ++i) {
848 memcpy(extraRowStart, lastRowStart, rowSize);
849 extraRowStart += rowSize;
850 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000851 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000852 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
853 texels.get()));
854 }
855 if (extraW) {
856 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
857 uint8_t* extraTexel = (uint8_t*)texels.get();
858 for (uint32_t j = 0; j < desc.fHeight; ++j) {
859 for (uint32_t i = 0; i < extraW; ++i) {
860 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
861 extraTexel += glDesc.fUploadByteCount;
862 }
863 edgeTexel += rowSize;
864 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000865 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000866 desc.fHeight, glDesc.fUploadFormat,
867 glDesc.fUploadType, texels.get()));
868 }
869 if (extraW && extraH) {
870 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
871 - glDesc.fUploadByteCount;
872 uint8_t* extraTexel = (uint8_t*)texels.get();
873 for (uint32_t i = 0; i < extraW*extraH; ++i) {
874 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
875 extraTexel += glDesc.fUploadByteCount;
876 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000877 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000878 extraW, extraH, glDesc.fUploadFormat,
879 glDesc.fUploadType, texels.get()));
880 }
881
882 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000883 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000884 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
885 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000886 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000887 }
888 }
889
890 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
891
892 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
893 rtIDs.fStencilRenderbufferID = 0;
894 rtIDs.fMSColorRenderbufferID = 0;
895 rtIDs.fRTFBOID = 0;
896 rtIDs.fTexFBOID = 0;
897 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000898 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000899
900 if (renderTarget) {
901#if GR_COLLECT_STATS
902 ++fStats.fRenderTargetCreateCnt;
903#endif
904 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000905 GrGLenum status;
906 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000907
908 // If need have both RT flag and srcData we have
909 // to invert the data before uploading because FBO
910 // will be rendered bottom up
911 GrAssert(NULL == srcData);
912 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
913
twiz@google.com59a190b2011-03-14 21:23:01 +0000914 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000915 GrAssert(rtIDs.fTexFBOID);
916
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000917 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000918 // to one and then resolve to the texture bound to the other.
919 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000920 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000921 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000922 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000923 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
924 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000925 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000926 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000927 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
928 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000929 return return_null_texture();
930 }
931 } else {
932 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
933 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000934 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000935 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000936 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000937 }
938
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000939 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000940 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000941 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000942 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000943
twiz@google.com0f31ca72011-03-18 17:38:11 +0000944 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000945
946 const StencilFormat* stencilFormats = GrGLStencilFormats();
947 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000948 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000949 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000950 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000951 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000952 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000953 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000954 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000955 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000956 glDesc.fAllocWidth,
957 glDesc.fAllocHeight));
958 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000959 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000960 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000961 glDesc.fAllocWidth,
962 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000963 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000964 err = GrGLGetGLInterface()->fGetError();
965 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000966 continue;
967 }
968 }
969 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
970 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000971 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000972 rtIDs.fMSColorRenderbufferID));
973 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000974 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000975 samples,
976 msColorRenderbufferFormat,
977 glDesc.fAllocWidth,
978 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000979 err = GrGLGetGLInterface()->fGetError();
980 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000981 continue;
982 }
983 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000984 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000985
986#if GR_COLLECT_STATS
987 ++fStats.fRenderTargetChngCnt;
988#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000989 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
990 GR_GL_COLOR_ATTACHMENT0,
991 GR_GL_TEXTURE_2D,
992 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000993 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000994 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
995 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000996 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
997 status, desc.fWidth, desc.fHeight);
998 continue;
999 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001000 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001001 #if GR_COLLECT_STATS
1002 ++fStats.fRenderTargetChngCnt;
1003 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001004 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1005 GR_GL_COLOR_ATTACHMENT0,
1006 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001007 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001008
1009 }
1010 if (rtIDs.fStencilRenderbufferID) {
1011 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001012 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1013 GR_GL_STENCIL_ATTACHMENT,
1014 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001015 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001016 // if it is a packed format bind to depth also, otherwise
1017 // we may get an unsupported fbo completeness result
1018 if (stencilFormats[i].fPacked) {
1019 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1020 GR_GL_DEPTH_ATTACHMENT,
1021 GR_GL_RENDERBUFFER,
1022 rtIDs.fStencilRenderbufferID));
1023 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001024 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001025 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001026
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001027 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001028 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1029 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001030 // undo the depth bind
1031 if (rtIDs.fStencilRenderbufferID &&
1032 stencilFormats[i].fPacked) {
1033 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1034 GR_GL_DEPTH_ATTACHMENT,
1035 GR_GL_RENDERBUFFER,
1036 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001037 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001038 continue;
1039 }
1040 // we're successful!
1041 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001042 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001043 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001044 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001045 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001046 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001047 }
1048 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001049 break;
1050 }
1051 if (failed) {
1052 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001053 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001054 }
1055 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001056 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001057 }
1058 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001059 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001060 }
1061 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001062 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001063 }
1064 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1065 return return_null_texture();
1066 }
1067 }
1068#ifdef TRACE_TEXTURE_CREATION
1069 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1070 tex->fTextureID, width, height, tex->fUploadByteCount);
1071#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001072 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001073
1074 if (0 != rtIDs.fTexFBOID) {
1075 GrRenderTarget* rt = tex->asRenderTarget();
1076 // We've messed with FBO state but may not have set the correct viewport
1077 // so just dirty the rendertarget state to force a resend.
1078 fHWDrawState.fRenderTarget = NULL;
1079
1080 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001081 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001082 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1083 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001084 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001085 fCurrDrawState.fRenderTarget = rtSave;
1086 }
1087 }
1088 return tex;
1089}
1090
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001091GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001092 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001093 GR_GL(GenBuffers(1, &id));
1094 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001095 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001096 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 GrGLClearErr();
1098 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001099 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1100 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1101 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001102 GR_GL(DeleteBuffers(1, &id));
1103 // deleting bound buffer does implicit bind to 0
1104 fHWGeometryState.fVertexBuffer = NULL;
1105 return NULL;
1106 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001107 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001108 size, dynamic);
1109 fHWGeometryState.fVertexBuffer = vertexBuffer;
1110 return vertexBuffer;
1111 }
1112 return NULL;
1113}
1114
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001115GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001116 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001117 GR_GL(GenBuffers(1, &id));
1118 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001119 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001120 GrGLClearErr();
1121 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001122 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1123 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1124 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001125 GR_GL(DeleteBuffers(1, &id));
1126 // deleting bound buffer does implicit bind to 0
1127 fHWGeometryState.fIndexBuffer = NULL;
1128 return NULL;
1129 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001130 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001131 size, dynamic);
1132 fHWGeometryState.fIndexBuffer = indexBuffer;
1133 return indexBuffer;
1134 }
1135 return NULL;
1136}
1137
reed@google.comac10a2d2010-12-22 21:39:39 +00001138void GrGpuGL::flushScissor(const GrIRect* rect) {
1139 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001140 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001141 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001142
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001143 GrGLIRect scissor;
1144 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001145 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001146 rect->width(), rect->height());
1147 if (scissor.contains(vp)) {
1148 rect = NULL;
1149 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001150 }
1151
1152 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001153 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001154 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001155 fHWBounds.fScissorRect = scissor;
1156 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001157 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001158 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001159 fHWBounds.fScissorEnabled = true;
1160 }
1161 } else {
1162 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001163 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001164 fHWBounds.fScissorEnabled = false;
1165 }
1166 }
1167}
1168
bsalomon@google.com398109c2011-04-14 18:40:27 +00001169void GrGpuGL::onClear(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001170 if (NULL == fCurrDrawState.fRenderTarget) {
1171 return;
1172 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001173 flushRenderTarget();
1174 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001175 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001176 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001177 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001178 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001179 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001180 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1181 GrColorUnpackG(color)/255.f,
1182 GrColorUnpackB(color)/255.f,
1183 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001184 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001185}
1186
bsalomon@google.com398109c2011-04-14 18:40:27 +00001187void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001188 if (NULL == fCurrDrawState.fRenderTarget) {
1189 return;
1190 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001191 flushRenderTarget();
1192 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001193 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001194 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001195 }
1196 GR_GL(StencilMask(mask));
1197 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001198 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001199 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001200}
1201
bsalomon@google.com398109c2011-04-14 18:40:27 +00001202void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001203 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001204#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001205 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001206 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001207 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001208#else
1209 // we could just clear the clip bit but when we go through
1210 // angle a partial stencil mask will cause clears to be
1211 // turned into draws. Our contract on GrDrawTarget says that
1212 // changing the clip between stencil passes may or may not
1213 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001214 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001215#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001216 flushRenderTarget();
1217 flushScissor(&rect);
1218 GR_GL(StencilMask(clipStencilMask));
1219 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001220 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001221 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001222}
1223
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001224void GrGpuGL::onForceRenderTargetFlush() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001225 flushRenderTarget();
1226}
1227
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001228bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1229 int left, int top, int width, int height,
1230 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001231 GrGLenum internalFormat; // we don't use this for glReadPixels
1232 GrGLenum format;
1233 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001234 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1235 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001236 }
1237 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1238 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1239 switch (tgt->getResolveType()) {
1240 case GrGLRenderTarget::kCantResolve_ResolveType:
1241 return false;
1242 case GrGLRenderTarget::kAutoResolves_ResolveType:
1243 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1244 fCurrDrawState.fRenderTarget = target;
1245 flushRenderTarget();
1246 break;
1247 case GrGLRenderTarget::kCanResolve_ResolveType:
1248 resolveRenderTarget(tgt);
1249 // we don't track the state of the READ FBO ID.
1250 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1251 break;
1252 default:
1253 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001254 }
1255
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001256 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001257
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001258 // the read rect is viewport-relative
1259 GrGLIRect readRect;
1260 readRect.setRelativeTo(glvp, left, top, width, height);
1261 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001262 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001263 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001264
1265 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1266 // API presents top-to-bottom
1267 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001268 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001269 GrAutoMalloc rowStorage(stride);
1270 void* tmp = rowStorage.get();
1271
1272 const int halfY = height >> 1;
1273 char* top = reinterpret_cast<char*>(buffer);
1274 char* bottom = top + (height - 1) * stride;
1275 for (int y = 0; y < halfY; y++) {
1276 memcpy(tmp, top, stride);
1277 memcpy(top, bottom, stride);
1278 memcpy(bottom, tmp, stride);
1279 top += stride;
1280 bottom -= stride;
1281 }
1282 }
1283 return true;
1284}
1285
1286void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001287
1288 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1289
reed@google.comac10a2d2010-12-22 21:39:39 +00001290 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1291 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001292 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001293 #if GR_COLLECT_STATS
1294 ++fStats.fRenderTargetChngCnt;
1295 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001296 rt->flagAsNeedingResolve();
reed@google.comac10a2d2010-12-22 21:39:39 +00001297 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001298 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1299 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001300 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1301 }
1302 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001303 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001304 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001305 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001306 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001307 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001308 fHWBounds.fViewportRect = vp;
1309 }
1310 }
1311}
1312
twiz@google.com0f31ca72011-03-18 17:38:11 +00001313GrGLenum gPrimitiveType2GLMode[] = {
1314 GR_GL_TRIANGLES,
1315 GR_GL_TRIANGLE_STRIP,
1316 GR_GL_TRIANGLE_FAN,
1317 GR_GL_POINTS,
1318 GR_GL_LINES,
1319 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001320};
1321
bsalomon@google.comd302f142011-03-03 13:54:13 +00001322#define SWAP_PER_DRAW 0
1323
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001324#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001325 #if GR_MAC_BUILD
1326 #include <AGL/agl.h>
1327 #elif GR_WIN32_BUILD
1328 void SwapBuf() {
1329 DWORD procID = GetCurrentProcessId();
1330 HWND hwnd = GetTopWindow(GetDesktopWindow());
1331 while(hwnd) {
1332 DWORD wndProcID = 0;
1333 GetWindowThreadProcessId(hwnd, &wndProcID);
1334 if(wndProcID == procID) {
1335 SwapBuffers(GetDC(hwnd));
1336 }
1337 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1338 }
1339 }
1340 #endif
1341#endif
1342
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001343void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1344 uint32_t startVertex,
1345 uint32_t startIndex,
1346 uint32_t vertexCount,
1347 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001348 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1349
twiz@google.com0f31ca72011-03-18 17:38:11 +00001350 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001351
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001352 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1353 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1354
1355 // our setupGeometry better have adjusted this to zero since
1356 // DrawElements always draws from the begining of the arrays for idx 0.
1357 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001358
1359 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001360 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001361#if SWAP_PER_DRAW
1362 glFlush();
1363 #if GR_MAC_BUILD
1364 aglSwapBuffers(aglGetCurrentContext());
1365 int set_a_break_pt_here = 9;
1366 aglSwapBuffers(aglGetCurrentContext());
1367 #elif GR_WIN32_BUILD
1368 SwapBuf();
1369 int set_a_break_pt_here = 9;
1370 SwapBuf();
1371 #endif
1372#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001373}
1374
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001375void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1376 uint32_t startVertex,
1377 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001378 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1379
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001380 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1381
1382 // our setupGeometry better have adjusted this to zero.
1383 // DrawElements doesn't take an offset so we always adjus the startVertex.
1384 GrAssert(0 == startVertex);
1385
1386 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1387 // account for startVertex in the DrawElements case. So we always
1388 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001389 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001390#if SWAP_PER_DRAW
1391 glFlush();
1392 #if GR_MAC_BUILD
1393 aglSwapBuffers(aglGetCurrentContext());
1394 int set_a_break_pt_here = 9;
1395 aglSwapBuffers(aglGetCurrentContext());
1396 #elif GR_WIN32_BUILD
1397 SwapBuf();
1398 int set_a_break_pt_here = 9;
1399 SwapBuf();
1400 #endif
1401#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001402}
1403
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001404void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001405
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001406 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001407 GrAssert(kNone_MSFBO != fMSFBOType);
1408 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001409 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001410 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001411 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001412 rt->textureFBOID()));
1413 #if GR_COLLECT_STATS
1414 ++fStats.fRenderTargetChngCnt;
1415 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001416 // make sure we go through flushRenderTarget() since we've modified
1417 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001418 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001419 const GrGLIRect& vp = rt->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001420
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001421 if (kAppleES_MSFBO == fMSFBOType) {
1422 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001423 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001424 GR_GL(Scissor(vp.fLeft, vp.fBottom,
1425 vp.fWidth, vp.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001426 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001427 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001428 fHWBounds.fScissorEnabled = true;
1429 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001430 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001431 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001432 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1433 flushScissor(NULL);
1434 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001435 int right = vp.fLeft + vp.fWidth;
1436 int top = vp.fBottom + vp.fHeight;
1437 GR_GL(BlitFramebuffer(vp.fLeft, vp.fBottom, right, top,
1438 vp.fLeft, vp.fBottom, right, top,
1439 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001440 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001441 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001442 }
1443}
1444
twiz@google.com0f31ca72011-03-18 17:38:11 +00001445static const GrGLenum grToGLStencilFunc[] = {
1446 GR_GL_ALWAYS, // kAlways_StencilFunc
1447 GR_GL_NEVER, // kNever_StencilFunc
1448 GR_GL_GREATER, // kGreater_StencilFunc
1449 GR_GL_GEQUAL, // kGEqual_StencilFunc
1450 GR_GL_LESS, // kLess_StencilFunc
1451 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1452 GR_GL_EQUAL, // kEqual_StencilFunc,
1453 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001454};
1455GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1456GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1457GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1458GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1459GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1460GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1461GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1462GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1463GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1464
twiz@google.com0f31ca72011-03-18 17:38:11 +00001465static const GrGLenum grToGLStencilOp[] = {
1466 GR_GL_KEEP, // kKeep_StencilOp
1467 GR_GL_REPLACE, // kReplace_StencilOp
1468 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1469 GR_GL_INCR, // kIncClamp_StencilOp
1470 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1471 GR_GL_DECR, // kDecClamp_StencilOp
1472 GR_GL_ZERO, // kZero_StencilOp
1473 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001474};
1475GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1476GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1477GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1478GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1479GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1480GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1481GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1482GR_STATIC_ASSERT(6 == kZero_StencilOp);
1483GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1484
reed@google.comac10a2d2010-12-22 21:39:39 +00001485void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001486 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001487
1488 // use stencil for clipping if clipping is enabled and the clip
1489 // has been written into the stencil.
1490 bool stencilClip = fClipState.fClipInStencil &&
1491 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001492 bool stencilChange = fHWStencilClip != stencilClip ||
1493 fHWDrawState.fStencilSettings != *settings ||
1494 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1495 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001496
1497 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001498
bsalomon@google.comd302f142011-03-03 13:54:13 +00001499 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1500 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001501
bsalomon@google.comd302f142011-03-03 13:54:13 +00001502 if (settings->isDisabled()) {
1503 if (stencilClip) {
1504 settings = &gClipStencilSettings;
1505 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001506 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001507
1508 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001509 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001510 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001511 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001512 #if GR_DEBUG
1513 if (!fStencilWrapOpsSupport) {
1514 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1515 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1516 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1517 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1518 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1519 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1520 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1521 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1522 }
1523 #endif
1524 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1525 GrAssert(stencilBits ||
1526 (GrStencilSettings::gDisabled ==
1527 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001528 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1529 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001530
1531 unsigned int frontRef = settings->fFrontFuncRef;
1532 unsigned int frontMask = settings->fFrontFuncMask;
1533 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001534 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001535
1536 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1537
1538 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1539 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1540 } else {
1541 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1542
1543 ConvertStencilFuncAndMask(settings->fFrontFunc,
1544 stencilClip,
1545 clipStencilMask,
1546 userStencilMask,
1547 &frontRef,
1548 &frontMask);
1549 frontWriteMask &= userStencilMask;
1550 }
1551 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001552 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001553 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001554 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001555 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001556 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001557 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001558 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001559 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001560 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001561
1562 unsigned int backRef = settings->fBackFuncRef;
1563 unsigned int backMask = settings->fBackFuncMask;
1564 unsigned int backWriteMask = settings->fBackWriteMask;
1565
1566
1567 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1568 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1569 backFunc = grToGLStencilFunc[settings->fBackFunc];
1570 } else {
1571 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1572 ConvertStencilFuncAndMask(settings->fBackFunc,
1573 stencilClip,
1574 clipStencilMask,
1575 userStencilMask,
1576 &backRef,
1577 &backMask);
1578 backWriteMask &= userStencilMask;
1579 }
1580
twiz@google.com0f31ca72011-03-18 17:38:11 +00001581 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1582 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1583 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1584 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1585 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001586 grToGLStencilOp[settings->fFrontPassOp],
1587 grToGLStencilOp[settings->fFrontPassOp]));
1588
twiz@google.com0f31ca72011-03-18 17:38:11 +00001589 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001590 grToGLStencilOp[settings->fBackPassOp],
1591 grToGLStencilOp[settings->fBackPassOp]));
1592 } else {
1593 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1594 GR_GL(StencilMask(frontWriteMask));
1595 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1596 grToGLStencilOp[settings->fFrontPassOp],
1597 grToGLStencilOp[settings->fFrontPassOp]));
1598 }
1599 }
1600 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001601 fHWStencilClip = stencilClip;
1602 }
1603}
1604
bsalomon@google.com0650e812011-04-08 18:07:53 +00001605bool GrGpuGL::useSmoothLines() {
1606 // there is a conflict between using smooth lines and our use of
1607 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1608 // but not in a premul-alpha way. So we only use them when our alpha
1609 // is 0xff.
1610
1611 // TODO: write a smarter line frag shader.
1612
1613 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1614 canDisableBlend();
1615}
1616
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001617void GrGpuGL::flushAAState(GrPrimitiveType type) {
1618 if (GR_GL_SUPPORT_DESKTOP) {
1619 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1620 // smooth lines.
1621
1622 // we prefer smooth lines over multisampled lines
1623 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001624 if (GrIsPrimTypeLines(type)) {
1625 bool smooth = useSmoothLines();
1626 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001627 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1628 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001629 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001630 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1631 fHWAAState.fSmoothLineEnabled = false;
1632 }
1633 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1634 fHWAAState.fMSAAEnabled) {
1635 GR_GL(Disable(GR_GL_MULTISAMPLE));
1636 fHWAAState.fMSAAEnabled = false;
1637 }
1638 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1639 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1640 fHWAAState.fMSAAEnabled) {
1641 if (fHWAAState.fMSAAEnabled) {
1642 GR_GL(Disable(GR_GL_MULTISAMPLE));
1643 fHWAAState.fMSAAEnabled = false;
1644 } else {
1645 GR_GL(Enable(GR_GL_MULTISAMPLE));
1646 fHWAAState.fMSAAEnabled = true;
1647 }
1648 }
1649 }
1650}
1651
bsalomon@google.com0650e812011-04-08 18:07:53 +00001652void GrGpuGL::flushBlend(GrPrimitiveType type) {
1653 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1654 if (fHWBlendDisabled) {
1655 GR_GL(Enable(GR_GL_BLEND));
1656 fHWBlendDisabled = false;
1657 }
1658 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1659 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1660 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1661 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1662 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1663 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1664 }
1665 } else {
1666 bool blendOff = canDisableBlend();
1667 if (fHWBlendDisabled != blendOff) {
1668 if (blendOff) {
1669 GR_GL(Disable(GR_GL_BLEND));
1670 } else {
1671 GR_GL(Enable(GR_GL_BLEND));
1672 }
1673 fHWBlendDisabled = blendOff;
1674 }
1675 if (!blendOff) {
1676 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1677 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1678 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1679 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1680 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1681 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1682 }
1683 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1684 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1685 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1686
1687 float c[] = {
1688 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1689 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1690 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1691 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1692 };
1693 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1694 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1695 }
1696 }
1697 }
1698}
1699
bsalomon@google.comffca4002011-02-22 20:34:01 +00001700bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001701
1702 // GrGpu::setupClipAndFlushState should have already checked this
1703 // and bailed if not true.
1704 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001705
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001706 for (int s = 0; s < kNumStages; ++s) {
1707 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001708
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001709 // bind texture and set sampler state
1710 if (usingTexture) {
1711 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001712
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001713 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001714 // if we created a rt/tex and rendered to it without using a
1715 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001716 // the last bound texture, but it needs resolving. So keep this
1717 // out of the "last != next" check.
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001718 GrGLRenderTarget* texRT =
1719 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1720 if (NULL != texRT) {
1721 resolveRenderTarget(texRT);
1722 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001723
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001724 if (fHWDrawState.fTextures[s] != nextTexture) {
1725 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001726 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001727 #if GR_COLLECT_STATS
1728 ++fStats.fTextureChngCnt;
1729 #endif
1730 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1731 fHWDrawState.fTextures[s] = nextTexture;
1732 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001733
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001734 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001735 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001736 nextTexture->getTexParams();
1737 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001738
twiz@google.com0f31ca72011-03-18 17:38:11 +00001739 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1740 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001741 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001742 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001743 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001744 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001745
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001746 if (newTexParams.fFilter != oldTexParams.fFilter) {
1747 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001748 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1749 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001750 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001751 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1752 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001753 newTexParams.fFilter));
1754 }
1755 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1756 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001757 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1758 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001759 newTexParams.fWrapS));
1760 }
1761 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1762 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001763 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1764 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001765 newTexParams.fWrapT));
1766 }
1767 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001768
1769 // The texture matrix has to compensate for texture width/height
1770 // and NPOT-embedded-in-POT
1771 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001772 } else {
1773 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001774 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001775 }
1776 }
1777 }
1778
1779 flushRenderTarget();
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001780 flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001781 flushBlend(type);
1782
reed@google.comac10a2d2010-12-22 21:39:39 +00001783 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1784 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1785 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001786 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001787 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001788 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001789 }
1790 }
1791
bsalomon@google.comd302f142011-03-03 13:54:13 +00001792 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1793 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001794 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001795 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001796 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001797 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001798 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001799 }
1800 GR_GL(ColorMask(mask, mask, mask, mask));
1801 }
1802
bsalomon@google.comd302f142011-03-03 13:54:13 +00001803 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1804 switch (fCurrDrawState.fDrawFace) {
1805 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001806 GR_GL(Enable(GR_GL_CULL_FACE));
1807 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001808 break;
1809 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001810 GR_GL(Enable(GR_GL_CULL_FACE));
1811 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001812 break;
1813 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001814 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001815 break;
1816 default:
1817 GrCrash("Unknown draw face.");
1818 }
1819 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1820 }
1821
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001822#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001823 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001824 for (int s = 0; s < kNumStages; ++s) {
1825 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1826 NULL == fCurrDrawState.fRenderTarget ||
1827 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001828 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001829 fCurrDrawState.fRenderTarget);
1830 }
1831#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001832
reed@google.comac10a2d2010-12-22 21:39:39 +00001833 flushStencil();
1834
bsalomon@google.comd302f142011-03-03 13:54:13 +00001835 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001836 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001837 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001838}
1839
1840void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001841 if (fHWGeometryState.fVertexBuffer != buffer) {
1842 fHWGeometryState.fArrayPtrsDirty = true;
1843 fHWGeometryState.fVertexBuffer = buffer;
1844 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001845}
1846
1847void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001848 if (fHWGeometryState.fVertexBuffer == buffer) {
1849 // deleting bound buffer does implied bind to 0
1850 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001851 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001852 }
1853}
1854
1855void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1856 fGeometrySrc.fIndexBuffer = buffer;
1857}
1858
1859void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001860 if (fHWGeometryState.fIndexBuffer == buffer) {
1861 // deleting bound buffer does implied bind to 0
1862 fHWGeometryState.fIndexBuffer = NULL;
1863 }
1864}
1865
reed@google.comac10a2d2010-12-22 21:39:39 +00001866void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1867 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001868 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001869 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001870 }
1871 if (fHWDrawState.fRenderTarget == renderTarget) {
1872 fHWDrawState.fRenderTarget = NULL;
1873 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001874}
1875
1876void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001877 for (int s = 0; s < kNumStages; ++s) {
1878 if (fCurrDrawState.fTextures[s] == texture) {
1879 fCurrDrawState.fTextures[s] = NULL;
1880 }
1881 if (fHWDrawState.fTextures[s] == texture) {
1882 // deleting bound texture does implied bind to 0
1883 fHWDrawState.fTextures[s] = NULL;
1884 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001885 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001886}
1887
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001888bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001889 GrGLenum* internalFormat,
1890 GrGLenum* format,
1891 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001892 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001893 case kRGBA_8888_GrPixelConfig:
1894 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001895 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001896 if (GR_GL_SUPPORT_ES) {
1897 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1898 // format for a BGRA is BGRA not RGBA (as on desktop)
1899 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1900 } else {
1901 *internalFormat = GR_GL_RGBA;
1902 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001903 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001904 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001905 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001906 *format = GR_GL_RGB;
1907 *internalFormat = GR_GL_RGB;
1908 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001909 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001910 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001911 *format = GR_GL_RGBA;
1912 *internalFormat = GR_GL_RGBA;
1913 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001914 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001915 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001916 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001917 *format = GR_GL_PALETTE8_RGBA8;
1918 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001919 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001920 } else {
1921 return false;
1922 }
1923 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001924 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001925 *format = GR_GL_ALPHA;
1926 *internalFormat = GR_GL_ALPHA;
1927 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001928 break;
1929 default:
1930 return false;
1931 }
1932 return true;
1933}
1934
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001935void GrGpuGL::setTextureUnit(int unit) {
1936 GrAssert(unit >= 0 && unit < kNumStages);
1937 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001938 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001939 fActiveTextureUnitIdx = unit;
1940 }
1941}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001942
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001943void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001944 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1945 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001946 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1947 }
1948}
1949
reed@google.comac10a2d2010-12-22 21:39:39 +00001950/* On ES the internalFormat and format must match for TexImage and we use
1951 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1952 decide the internalFormat. However, on ES internalFormat for
1953 RenderBufferStorage* has to be a specific format (not a base format like
1954 GL_RGBA).
1955 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001956bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001957 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001958 case kRGBA_8888_GrPixelConfig:
1959 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001960 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001961 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001962 return true;
1963 } else {
1964 return false;
1965 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001966 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001967 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1968 // with FBO extension desktop GL has
1969 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001970 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001971 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001972 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001973 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001974 return true;
1975 default:
1976 return false;
1977 }
1978}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001979
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001980void GrGpuGL::resetDirtyFlags() {
1981 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1982}
1983
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001984void GrGpuGL::setBuffers(bool indexed,
1985 int* extraVertexOffset,
1986 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001987
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001988 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001989
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001990 GrGLVertexBuffer* vbuf;
1991 switch (fGeometrySrc.fVertexSrc) {
1992 case kBuffer_GeometrySrcType:
1993 *extraVertexOffset = 0;
1994 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1995 break;
1996 case kArray_GeometrySrcType:
1997 case kReserved_GeometrySrcType:
1998 finalizeReservedVertices();
1999 *extraVertexOffset = fCurrPoolStartVertex;
2000 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2001 break;
2002 default:
2003 vbuf = NULL; // suppress warning
2004 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002005 }
2006
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002007 GrAssert(NULL != vbuf);
2008 GrAssert(!vbuf->isLocked());
2009 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002010 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002011 fHWGeometryState.fArrayPtrsDirty = true;
2012 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002013 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002014
2015 if (indexed) {
2016 GrAssert(NULL != extraIndexOffset);
2017
2018 GrGLIndexBuffer* ibuf;
2019 switch (fGeometrySrc.fIndexSrc) {
2020 case kBuffer_GeometrySrcType:
2021 *extraIndexOffset = 0;
2022 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2023 break;
2024 case kArray_GeometrySrcType:
2025 case kReserved_GeometrySrcType:
2026 finalizeReservedIndices();
2027 *extraIndexOffset = fCurrPoolStartIndex;
2028 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2029 break;
2030 default:
2031 ibuf = NULL; // suppress warning
2032 GrCrash("Unknown geometry src type!");
2033 }
2034
2035 GrAssert(NULL != ibuf);
2036 GrAssert(!ibuf->isLocked());
2037 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002038 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002039 fHWGeometryState.fIndexBuffer = ibuf;
2040 }
2041 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002042}