blob: 1862784c1ec5c3edd1703460bcca9bcb456cbd0f [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
bsalomon@google.com1da07462011-03-10 14:51:57 +00002 Copyright 2011 Google Inc.
reed@google.comac10a2d2010-12-22 21:39:39 +00003
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#include "GrGpuGL.h"
18#include "GrMemory.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000019
twiz@google.com0f31ca72011-03-18 17:38:11 +000020static const GrGLuint GR_MAX_GLUINT = ~0;
21static const GrGLint GR_INVAL_GLINT = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000022
bsalomon@google.com316f99232011-01-13 21:28:12 +000023// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000024// mucking with the state of any of the stages.
bsalomon@google.com316f99232011-01-13 21:28:12 +000025static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000026
reed@google.comac10a2d2010-12-22 21:39:39 +000027#define SKIP_CACHE_CHECK true
28
twiz@google.com0f31ca72011-03-18 17:38:11 +000029static const GrGLenum gXfermodeCoeff2Blend[] = {
30 GR_GL_ZERO,
31 GR_GL_ONE,
32 GR_GL_SRC_COLOR,
33 GR_GL_ONE_MINUS_SRC_COLOR,
34 GR_GL_DST_COLOR,
35 GR_GL_ONE_MINUS_DST_COLOR,
36 GR_GL_SRC_ALPHA,
37 GR_GL_ONE_MINUS_SRC_ALPHA,
38 GR_GL_DST_ALPHA,
39 GR_GL_ONE_MINUS_DST_ALPHA,
40 GR_GL_CONSTANT_COLOR,
41 GR_GL_ONE_MINUS_CONSTANT_COLOR,
42 GR_GL_CONSTANT_ALPHA,
43 GR_GL_ONE_MINUS_CONSTANT_ALPHA,
reed@google.comac10a2d2010-12-22 21:39:39 +000044};
45
bsalomon@google.com080773c2011-03-15 19:09:25 +000046bool GrGpuGL::BlendCoefReferencesConstant(GrBlendCoeff coeff) {
47 static const bool gCoeffReferencesBlendConst[] = {
48 false,
49 false,
50 false,
51 false,
52 false,
53 false,
54 false,
55 false,
56 false,
57 false,
58 true,
59 true,
60 true,
61 true,
62 };
63 return gCoeffReferencesBlendConst[coeff];
64 GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
65}
66
67GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
68GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
69GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
70GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
71GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
72GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
73GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
74GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
75GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
76GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
77GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
78GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
79GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
80GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
81
82GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
83
reed@google.comac10a2d2010-12-22 21:39:39 +000084///////////////////////////////////////////////////////////////////////////////
85
bsalomon@google.comd302f142011-03-03 13:54:13 +000086void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
87 GrSamplerState::SampleMode mode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000088 GrMatrix* matrix) {
89 GrAssert(NULL != texture);
90 GrAssert(NULL != matrix);
91 if (GR_Scalar1 != texture->contentScaleX() ||
92 GR_Scalar1 != texture->contentScaleY()) {
93 if (GrSamplerState::kRadial_SampleMode == mode) {
94 GrMatrix scale;
95 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
96 matrix->postConcat(scale);
97 } else if (GrSamplerState::kNormal_SampleMode == mode) {
98 GrMatrix scale;
99 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
100 matrix->postConcat(scale);
101 } else {
102 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
103 }
104 }
105 GrGLTexture::Orientation orientation = texture->orientation();
106 if (GrGLTexture::kBottomUp_Orientation == orientation) {
107 GrMatrix invY;
108 invY.setAll(GR_Scalar1, 0, 0,
109 0, -GR_Scalar1, GR_Scalar1,
110 0, 0, GrMatrix::I()[8]);
111 matrix->postConcat(invY);
112 } else {
113 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
114 }
115}
116
bsalomon@google.comd302f142011-03-03 13:54:13 +0000117bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000118 const GrSamplerState& sampler) {
119 GrAssert(NULL != texture);
120 if (!sampler.getMatrix().isIdentity()) {
121 return false;
122 }
123 if (GR_Scalar1 != texture->contentScaleX() ||
124 GR_Scalar1 != texture->contentScaleY()) {
125 return false;
126 }
127 GrGLTexture::Orientation orientation = texture->orientation();
128 if (GrGLTexture::kBottomUp_Orientation == orientation) {
129 return false;
130 } else {
131 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
132 }
133 return true;
134}
135
136///////////////////////////////////////////////////////////////////////////////
137
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000138static bool gPrintStartupSpew;
139
twiz@google.com59a190b2011-03-14 21:23:01 +0000140static bool fbo_test(int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000141
twiz@google.com0f31ca72011-03-18 17:38:11 +0000142 GrGLint savedFBO;
143 GrGLint savedTexUnit;
144 GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000145 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000146
twiz@google.com0f31ca72011-03-18 17:38:11 +0000147 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000148
twiz@google.com0f31ca72011-03-18 17:38:11 +0000149 GrGLuint testFBO;
twiz@google.com59a190b2011-03-14 21:23:01 +0000150 GR_GL(GenFramebuffers(1, &testFBO));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000151 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000152 GrGLuint testRTTex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 GR_GL(GenTextures(1, &testRTTex));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000154 GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000155 // some implementations require texture to be mip-map complete before
156 // FBO with level 0 bound as color attachment will be framebuffer complete.
twiz@google.com0f31ca72011-03-18 17:38:11 +0000157 GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
158 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
159 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
160 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000161 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000162 GR_GL_TEXTURE_2D, testRTTex, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000163 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000164 GR_GL(DeleteFramebuffers(1, &testFBO));
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000166
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000167 GR_GL(ActiveTexture(savedTexUnit));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000168 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000169
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000170 return status == GR_GL_FRAMEBUFFER_COMPLETE;
reed@google.comac10a2d2010-12-22 21:39:39 +0000171}
172
reed@google.comac10a2d2010-12-22 21:39:39 +0000173GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000174
reed@google.comeeeb5a02010-12-23 15:12:59 +0000175 if (gPrintStartupSpew) {
176 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
177 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000178 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000179 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000180 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000181 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000182 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000183 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000184 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000185 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000186 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000187
188 GrGLClearErr();
189
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000190 resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000191
twiz@google.com0f31ca72011-03-18 17:38:11 +0000192 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000193 // check FS and fixed-function texture unit limits
194 // we only use textures in the fragment stage currently.
195 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000196 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
197 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
198 GrAssert(maxTextureUnits > kNumStages);
199 }
200 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
201 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
202 GrAssert(maxTextureUnits > kNumStages);
203 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000204
reed@google.comac10a2d2010-12-22 21:39:39 +0000205 ////////////////////////////////////////////////////////////////////////////
206 // Check for supported features.
207
208 int major, minor;
209 gl_version(&major, &minor);
210
twiz@google.com0f31ca72011-03-18 17:38:11 +0000211 GrGLint numFormats;
212 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
213 GrAutoSTMalloc<10, GrGLint> formats(numFormats);
214 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000216 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000217 f8bitPaletteSupport = true;
218 break;
219 }
220 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000221
222 if (gPrintStartupSpew) {
223 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
224 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000225
226 GR_STATIC_ASSERT(0 == kNone_AALevel);
227 GR_STATIC_ASSERT(1 == kLow_AALevel);
228 GR_STATIC_ASSERT(2 == kMed_AALevel);
229 GR_STATIC_ASSERT(3 == kHigh_AALevel);
230
231 memset(fAASamples, 0, sizeof(fAASamples));
232 fMSFBOType = kNone_MSFBO;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000233 if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000234 fMSFBOType = kApple_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000235 if (gPrintStartupSpew) {
236 GrPrintf("MSAA Support: APPLE ES EXT.\n");
237 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000238 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000239 else if (GR_GL_SUPPORT_DESKTOP && (
240 (major >= 3) ||
reed@google.comac10a2d2010-12-22 21:39:39 +0000241 has_gl_extension("GL_ARB_framebuffer_object") ||
242 (has_gl_extension("GL_EXT_framebuffer_multisample") &&
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000243 has_gl_extension("GL_EXT_framebuffer_blit")))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000244 fMSFBOType = kDesktop_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000245 if (gPrintStartupSpew) {
246 GrPrintf("MSAA Support: DESKTOP\n");
247 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000248 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000249 else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000250 if (gPrintStartupSpew) {
251 GrPrintf("MSAA Support: NONE\n");
252 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000253 }
254
255 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000256 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000257 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000258 if (maxSamples > 1 ) {
259 fAASamples[kNone_AALevel] = 0;
260 fAASamples[kLow_AALevel] = GrMax(2,
261 GrFixedFloorToInt((GR_FixedHalf) *
262 maxSamples));
263 fAASamples[kMed_AALevel] = GrMax(2,
264 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
265 maxSamples));
266 fAASamples[kHigh_AALevel] = maxSamples;
267 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000268 if (gPrintStartupSpew) {
269 GrPrintf("\tMax Samples: %d\n", maxSamples);
270 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000271 }
272
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000273 if (GR_GL_SUPPORT_DESKTOP) {
274 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
275 has_gl_extension("GL_EXT_stencil_wrap");
276 } else {
277 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
278 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000279 if (gPrintStartupSpew) {
280 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
281 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000282
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000283 if (GR_GL_SUPPORT_DESKTOP) {
284 // we could also look for GL_ATI_separate_stencil extension or
285 // GL_EXT_stencil_two_side but they use different function signatures
286 // than GL2.0+ (and than each other).
287 fTwoSidedStencilSupport = (major >= 2);
288 // supported on GL 1.4 and higher or by extension
289 fStencilWrapOpsSupport = (major > 1) ||
290 ((1 == major) && (minor >= 4)) ||
291 has_gl_extension("GL_EXT_stencil_wrap");
292 } else {
293 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
294 // an ES1 extension.
295 fTwoSidedStencilSupport = (major >= 2);
296 // stencil wrap support is in ES2, ES1 requires extension.
297 fStencilWrapOpsSupport = (major > 1) ||
298 has_gl_extension("GL_OES_stencil_wrap");
299 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000300 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000301 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
302 (fTwoSidedStencilSupport ? "YES" : "NO"),
303 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000304 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000305
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000306 if (GR_GL_SUPPORT_DESKTOP) {
307 fRGBA8Renderbuffer = true;
308 } else {
309 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
310 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000311 if (gPrintStartupSpew) {
312 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
313 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000314
315
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000316 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000317 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000318 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
319 }
320 }
321
322 if (GR_GL_SUPPORT_DESKTOP) {
323 fBufferLockSupport = true; // we require VBO support and the desktop VBO
324 // extension includes glMapBuffer.
325 } else {
326 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
327 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000328
reed@google.comeeeb5a02010-12-23 15:12:59 +0000329 if (gPrintStartupSpew) {
330 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
331 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000332
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000333 if (GR_GL_SUPPORT_DESKTOP) {
334 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
335 fNPOTTextureTileSupport = true;
336 fNPOTTextureSupport = true;
337 } else {
338 fNPOTTextureTileSupport = false;
339 fNPOTTextureSupport = false;
340 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000341 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000342 if (major >= 2) {
343 fNPOTTextureSupport = true;
344 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
345 } else {
346 fNPOTTextureSupport =
347 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
348 fNPOTTextureTileSupport = false;
349 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000350 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000351
reed@google.comac10a2d2010-12-22 21:39:39 +0000352 ////////////////////////////////////////////////////////////////////////////
353 // Experiments to determine limitations that can't be queried. TODO: Make
354 // these a preprocess that generate some compile time constants.
355
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000356 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000357
twiz@google.com59a190b2011-03-14 21:23:01 +0000358 bool simpleFBOSuccess = fbo_test(128, 128);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000359 if (gPrintStartupSpew) {
360 if (!simpleFBOSuccess) {
361 GrPrintf("FBO Sanity Test: FAILED\n");
362 } else {
363 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000364 }
365 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000366 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000367
reed@google.comac10a2d2010-12-22 21:39:39 +0000368 /* Experimentation has found that some GLs that support NPOT textures
369 do not support FBOs with a NPOT texture. They report "unsupported" FBO
370 status. I don't know how to explicitly query for this. Do an
371 experiment. Note they may support NPOT with a renderbuffer but not a
372 texture. Presumably, the implementation bloats the renderbuffer
373 internally to the next POT.
374 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000375 bool fNPOTRenderTargetSupport = false;
376 if (fNPOTTextureSupport) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000377 fNPOTRenderTargetSupport = fbo_test(200, 200);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000378 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000379
bsalomon@google.com0748f212011-02-01 22:56:16 +0000380 if (gPrintStartupSpew) {
381 if (fNPOTTextureSupport) {
382 GrPrintf("NPOT textures supported\n");
383 if (fNPOTTextureTileSupport) {
384 GrPrintf("NPOT texture tiling supported\n");
385 } else {
386 GrPrintf("NPOT texture tiling NOT supported\n");
387 }
388 if (fNPOTRenderTargetSupport) {
389 GrPrintf("NPOT render targets supported\n");
390 } else {
391 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000392 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000393 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000394 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000395 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000396 }
397
reed@google.comac10a2d2010-12-22 21:39:39 +0000398 /* The iPhone 4 has a restriction that for an FBO with texture color
399 attachment with height <= 8 then the width must be <= height. Here
400 we look for such a limitation.
401 */
402 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000403 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000404 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000405
reed@google.comeeeb5a02010-12-23 15:12:59 +0000406 if (gPrintStartupSpew) {
407 GrPrintf("Small height FBO texture experiments\n");
408 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000409
twiz@google.com0f31ca72011-03-18 17:38:11 +0000410 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
411 GrGLuint w = maxRenderSize;
412 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000413 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000414 if (gPrintStartupSpew) {
415 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
416 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000417 fMinRenderTargetHeight = i;
418 break;
419 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000420 if (gPrintStartupSpew) {
421 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
422 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000423 }
424 }
425 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
426
reed@google.comeeeb5a02010-12-23 15:12:59 +0000427 if (gPrintStartupSpew) {
428 GrPrintf("Small width FBO texture experiments\n");
429 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000430 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000431 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
432 GrGLuint w = i;
433 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000434 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000435 if (gPrintStartupSpew) {
436 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
437 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000438 fMinRenderTargetWidth = i;
439 break;
440 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000441 if (gPrintStartupSpew) {
442 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
443 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000444 }
445 }
446 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
447
twiz@google.com0f31ca72011-03-18 17:38:11 +0000448 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000449}
450
451GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000452}
453
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000454void GrGpuGL::resetContext() {
455 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000456 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000457 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000458
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000459 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000460 GR_GL(Disable(GR_GL_DEPTH_TEST));
461 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000462
twiz@google.com0f31ca72011-03-18 17:38:11 +0000463 GR_GL(Disable(GR_GL_CULL_FACE));
464 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000465 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000466
twiz@google.com0f31ca72011-03-18 17:38:11 +0000467 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000468 if (GR_GL_SUPPORT_DESKTOP) {
469 GR_GL(Disable(GR_GL_LINE_SMOOTH));
470 GR_GL(Disable(GR_GL_POINT_SMOOTH));
471 GR_GL(Disable(GR_GL_MULTISAMPLE));
472 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000473
twiz@google.com0f31ca72011-03-18 17:38:11 +0000474 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000475 fHWDrawState.fFlagBits = 0;
476
reed@google.comac10a2d2010-12-22 21:39:39 +0000477 // we only ever use lines in hairline mode
478 GR_GL(LineWidth(1));
479
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000480 // invalid
481 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000482
reed@google.comac10a2d2010-12-22 21:39:39 +0000483 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000484 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
485 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000486
487 fHWDrawState.fBlendConstant = 0x00000000;
488 GR_GL(BlendColor(0,0,0,0));
489
reed@google.comac10a2d2010-12-22 21:39:39 +0000490 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000491
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000492 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000493
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000494 for (int s = 0; s < kNumStages; ++s) {
495 fHWDrawState.fTextures[s] = NULL;
496 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
497 -GR_ScalarMax,
498 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000499
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000500 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000501 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000502
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000503 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000504 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000505 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000506 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000507
bsalomon@google.comd302f142011-03-03 13:54:13 +0000508 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000509 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000510 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000511
512 fHWGeometryState.fIndexBuffer = NULL;
513 fHWGeometryState.fVertexBuffer = NULL;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000514 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
515 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000516 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000517
twiz@google.com0f31ca72011-03-18 17:38:11 +0000518 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000519 fHWDrawState.fRenderTarget = NULL;
520}
521
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000522GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
reed@google.comac10a2d2010-12-22 21:39:39 +0000523 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000524 int stencilBits,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000525 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000526 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000527 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
528 rtIDs.fStencilRenderbufferID = 0;
529 rtIDs.fMSColorRenderbufferID = 0;
530 rtIDs.fTexFBOID = 0;
531 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000532 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000533
534 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000535 viewport.fLeft = 0;
536 viewport.fBottom = 0;
537 viewport.fWidth = width;
538 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000539
twiz@google.com0f31ca72011-03-18 17:38:11 +0000540 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
541 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000542
bsalomon@google.com1da07462011-03-10 14:51:57 +0000543 return new GrGLRenderTarget(rtIDs, NULL, stencilBits, viewport, NULL, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000544}
545
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000546GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000547
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000548 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000549
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000550 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000551 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
552 rtIDs.fMSColorRenderbufferID = 0;
553 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000554
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000555 GrGLIRect viewport;
556 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000557 GrGLuint stencilBits;
558 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000559
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000560 rtIDs.fOwnIDs = false;
561
bsalomon@google.com1da07462011-03-10 14:51:57 +0000562 return new GrGLRenderTarget(rtIDs, NULL, stencilBits, viewport, NULL, this);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000563}
564
bsalomon@google.com5782d712011-01-21 21:03:59 +0000565///////////////////////////////////////////////////////////////////////////////
566
twiz@google.com0f31ca72011-03-18 17:38:11 +0000567static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000568
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000569struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000570 GrGLenum fEnum;
571 GrGLuint fBits;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000572};
573
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000574const StencilFormat* GrGLStencilFormats() {
575 // defines stencil formats from more to less preferred
576 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000577 {GR_GL_STENCIL_INDEX8, 8},
578 {GR_GL_STENCIL_INDEX16, 16},
579 {GR_GL_DEPTH24_STENCIL8, 8},
580 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000581 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS},
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000582 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000583 {0, 0}
584 };
585
586 static const StencilFormat esStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000587 {GR_GL_STENCIL_INDEX8, 8},
588 {GR_GL_DEPTH24_STENCIL8, 8},
589 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000590 {0, 0}
591 };
592
593 if (GR_GL_SUPPORT_DESKTOP) {
594 return desktopStencilFormats;
595 } else {
596 return esStencilFormats;
597 }
598}
599
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000600// good to set a break-point here to know when createTexture fails
601static GrTexture* return_null_texture() {
602// GrAssert(!"null texture");
603 return NULL;
604}
605
606#if GR_DEBUG
607static size_t as_size_t(int x) {
608 return x;
609}
610#endif
611
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000612GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
613 const void* srcData,
614 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000615
616#if GR_COLLECT_STATS
617 ++fStats.fTextureCreateCnt;
618#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000619
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000620 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000621
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000622 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000623 GR_GL_NEAREST,
624 GR_GL_CLAMP_TO_EDGE,
625 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000626 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000627
reed@google.comac10a2d2010-12-22 21:39:39 +0000628 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000629 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000630
631 glDesc.fContentWidth = desc.fWidth;
632 glDesc.fContentHeight = desc.fHeight;
633 glDesc.fAllocWidth = desc.fWidth;
634 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000635 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000636 glDesc.fFormat = desc.fFormat;
637
638 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
639 if (!canBeTexture(desc.fFormat,
640 &internalFormat,
641 &glDesc.fUploadFormat,
642 &glDesc.fUploadType)) {
643 return return_null_texture();
644 }
645
646 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000647 GrGLint samples = fAASamples[desc.fAALevel];
reed@google.comac10a2d2010-12-22 21:39:39 +0000648 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
649 GrPrintf("AA RT requested but not supported on this platform.");
650 }
651
652 GR_GL(GenTextures(1, &glDesc.fTextureID));
653 if (!glDesc.fTextureID) {
654 return return_null_texture();
655 }
656
657 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
658
659 /*
660 * check if our srcData has extra bytes past each row. If so, we need
661 * to trim those off here, since GL doesn't let us pass the rowBytes as
662 * a parameter to glTexImage2D
663 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000664 if (GR_GL_SUPPORT_DESKTOP) {
665 if (srcData) {
666 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
667 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000668 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000669 } else {
670 GrAutoSMalloc<128 * 128> trimStorage;
671 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
672 if (srcData && (trimRowBytes < rowBytes)) {
673 size_t trimSize = desc.fHeight * trimRowBytes;
674 trimStorage.realloc(trimSize);
675 // now copy the data into our new storage, skipping the trailing bytes
676 const char* src = (const char*)srcData;
677 char* dst = (char*)trimStorage.get();
678 for (uint32_t y = 0; y < desc.fHeight; y++) {
679 memcpy(dst, src, trimRowBytes);
680 src += rowBytes;
681 dst += trimRowBytes;
682 }
683 // now point srcData to our trimmed version
684 srcData = trimStorage.get();
685 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000686 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000687
reed@google.comac10a2d2010-12-22 21:39:39 +0000688 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000689 if (!this->npotRenderTargetSupport()) {
690 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
691 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
692 }
693
reed@google.comac10a2d2010-12-22 21:39:39 +0000694 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
695 glDesc.fAllocWidth);
696 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
697 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000698 } else if (!this->npotTextureSupport()) {
699 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
700 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000701 }
702
twiz@google.com0f31ca72011-03-18 17:38:11 +0000703 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
704 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
705 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000706 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000707 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
708 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000709 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000710 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
711 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000712 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000713 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
714 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000715 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000716
twiz@google.com0f31ca72011-03-18 17:38:11 +0000717 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000718 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
719 supports8BitPalette()) {
720 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
721 GrAssert(desc.fWidth == glDesc.fAllocWidth);
722 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000723 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
724 kColorTableSize;
725 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000726 glDesc.fAllocWidth, glDesc.fAllocHeight,
727 0, imageSize, srcData));
728 GrGL_RestoreResetRowLength();
729 } else {
730 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
731 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000732 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000733 glDesc.fAllocWidth, glDesc.fAllocHeight,
734 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000735 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000736 desc.fHeight, glDesc.fUploadFormat,
737 glDesc.fUploadType, srcData));
738 GrGL_RestoreResetRowLength();
739
740 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
741 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
742 uint32_t maxTexels = extraW * extraH;
743 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
744 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
745
746 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
747
748 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
749 if (extraH) {
750 uint8_t* lastRowStart = (uint8_t*) srcData +
751 (desc.fHeight - 1) * rowSize;
752 uint8_t* extraRowStart = (uint8_t*)texels.get();
753
754 for (uint32_t i = 0; i < extraH; ++i) {
755 memcpy(extraRowStart, lastRowStart, rowSize);
756 extraRowStart += rowSize;
757 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000758 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000759 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
760 texels.get()));
761 }
762 if (extraW) {
763 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
764 uint8_t* extraTexel = (uint8_t*)texels.get();
765 for (uint32_t j = 0; j < desc.fHeight; ++j) {
766 for (uint32_t i = 0; i < extraW; ++i) {
767 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
768 extraTexel += glDesc.fUploadByteCount;
769 }
770 edgeTexel += rowSize;
771 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000772 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000773 desc.fHeight, glDesc.fUploadFormat,
774 glDesc.fUploadType, texels.get()));
775 }
776 if (extraW && extraH) {
777 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
778 - glDesc.fUploadByteCount;
779 uint8_t* extraTexel = (uint8_t*)texels.get();
780 for (uint32_t i = 0; i < extraW*extraH; ++i) {
781 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
782 extraTexel += glDesc.fUploadByteCount;
783 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000784 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000785 extraW, extraH, glDesc.fUploadFormat,
786 glDesc.fUploadType, texels.get()));
787 }
788
789 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000790 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000791 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
792 glDesc.fUploadType, srcData));
793 GrGL_RestoreResetRowLength();
794 }
795 }
796
797 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
798
799 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
800 rtIDs.fStencilRenderbufferID = 0;
801 rtIDs.fMSColorRenderbufferID = 0;
802 rtIDs.fRTFBOID = 0;
803 rtIDs.fTexFBOID = 0;
804 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000805 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000806
807 if (renderTarget) {
808#if GR_COLLECT_STATS
809 ++fStats.fRenderTargetCreateCnt;
810#endif
811 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000812 GrGLenum status;
813 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000814
815 // If need have both RT flag and srcData we have
816 // to invert the data before uploading because FBO
817 // will be rendered bottom up
818 GrAssert(NULL == srcData);
819 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
820
twiz@google.com59a190b2011-03-14 21:23:01 +0000821 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000822 GrAssert(rtIDs.fTexFBOID);
823
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000824 // If we are using multisampling and we will create two FBOS We render
825 // to one and then resolve to the texture bound to the other.
826 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000827 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000828 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000829 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000830 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
831 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000832 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000833 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000834 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
835 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000836 return return_null_texture();
837 }
838 } else {
839 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
840 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000841 if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000842 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000843 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000844 }
845
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000846 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000847 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000848 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000849 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000850
twiz@google.com0f31ca72011-03-18 17:38:11 +0000851 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000852
853 const StencilFormat* stencilFormats = GrGLStencilFormats();
854 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000855 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000856 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000857 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000858 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000859 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000860 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000861 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000862 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000863 glDesc.fAllocWidth,
864 glDesc.fAllocHeight));
865 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000866 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000867 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000868 glDesc.fAllocWidth,
869 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000870 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000871 err = GrGLGetGLInterface()->fGetError();
872 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000873 continue;
874 }
875 }
876 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
877 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000878 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000879 rtIDs.fMSColorRenderbufferID));
880 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000881 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000882 samples,
883 msColorRenderbufferFormat,
884 glDesc.fAllocWidth,
885 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000886 err = GrGLGetGLInterface()->fGetError();
887 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000888 continue;
889 }
890 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000891 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000892
893#if GR_COLLECT_STATS
894 ++fStats.fRenderTargetChngCnt;
895#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000896 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
897 GR_GL_COLOR_ATTACHMENT0,
898 GR_GL_TEXTURE_2D,
899 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000900 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000901 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
902 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000903 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
904 status, desc.fWidth, desc.fHeight);
905 continue;
906 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000907 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000908 #if GR_COLLECT_STATS
909 ++fStats.fRenderTargetChngCnt;
910 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000911 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
912 GR_GL_COLOR_ATTACHMENT0,
913 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000914 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000915
916 }
917 if (rtIDs.fStencilRenderbufferID) {
918 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000919 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
920 GR_GL_STENCIL_ATTACHMENT,
921 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000922 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000923 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000924 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000925
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000926 if (GR_GL_SUPPORT_DESKTOP) {
927 // On some implementations you have to be bound as DEPTH_STENCIL.
928 // (Even binding to DEPTH and STENCIL separately with the same
929 // buffer doesn't work.)
930 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000931 status != GR_GL_FRAMEBUFFER_COMPLETE) {
932 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
933 GR_GL_STENCIL_ATTACHMENT,
934 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000935 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000936 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
937 GR_GL_DEPTH_STENCIL_ATTACHMENT,
938 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000939 rtIDs.fStencilRenderbufferID));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000940 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000941 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000942 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000943 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000944 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
945 status, desc.fWidth, desc.fHeight);
946 if (GR_GL_SUPPORT_DESKTOP) {
947 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000948 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
949 GR_GL_DEPTH_STENCIL_ATTACHMENT,
950 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000951 0));
952 }
953 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000954 continue;
955 }
956 // we're successful!
957 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000958 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000959 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000960 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000961 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000962 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000963 }
964 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000965 break;
966 }
967 if (failed) {
968 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000969 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000970 }
971 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000972 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000973 }
974 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000975 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000976 }
977 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000978 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000979 }
980 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
981 return return_null_texture();
982 }
983 }
984#ifdef TRACE_TEXTURE_CREATION
985 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
986 tex->fTextureID, width, height, tex->fUploadByteCount);
987#endif
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000988 GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, DEFAULT_PARAMS, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000989
990 if (0 != rtIDs.fTexFBOID) {
991 GrRenderTarget* rt = tex->asRenderTarget();
992 // We've messed with FBO state but may not have set the correct viewport
993 // so just dirty the rendertarget state to force a resend.
994 fHWDrawState.fRenderTarget = NULL;
995
996 // clear the new stencil buffer if we have one
997 if (!(desc.fFlags & kNoPathRendering_TextureFlag)) {
998 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
999 fCurrDrawState.fRenderTarget = rt;
1000 eraseStencil(0, ~0);
1001 fCurrDrawState.fRenderTarget = rtSave;
1002 }
1003 }
1004 return tex;
1005}
1006
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001007GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001008 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001009 GR_GL(GenBuffers(1, &id));
1010 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001011 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001012 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001013 GrGLClearErr();
1014 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001015 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1016 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1017 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001018 GR_GL(DeleteBuffers(1, &id));
1019 // deleting bound buffer does implicit bind to 0
1020 fHWGeometryState.fVertexBuffer = NULL;
1021 return NULL;
1022 }
1023 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this,
1024 size, dynamic);
1025 fHWGeometryState.fVertexBuffer = vertexBuffer;
1026 return vertexBuffer;
1027 }
1028 return NULL;
1029}
1030
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001031GrIndexBuffer* GrGpuGL::createIndexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001032 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001033 GR_GL(GenBuffers(1, &id));
1034 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001035 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001036 GrGLClearErr();
1037 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001038 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1039 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1040 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001041 GR_GL(DeleteBuffers(1, &id));
1042 // deleting bound buffer does implicit bind to 0
1043 fHWGeometryState.fIndexBuffer = NULL;
1044 return NULL;
1045 }
1046 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this,
1047 size, dynamic);
1048 fHWGeometryState.fIndexBuffer = indexBuffer;
1049 return indexBuffer;
1050 }
1051 return NULL;
1052}
1053
reed@google.comac10a2d2010-12-22 21:39:39 +00001054void GrGpuGL::flushScissor(const GrIRect* rect) {
1055 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001056 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001057 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001058
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001059 GrGLIRect scissor;
1060 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001061 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001062 rect->width(), rect->height());
1063 if (scissor.contains(vp)) {
1064 rect = NULL;
1065 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001066 }
1067
1068 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001069 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001070 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001071 fHWBounds.fScissorRect = scissor;
1072 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001073 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001074 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001075 fHWBounds.fScissorEnabled = true;
1076 }
1077 } else {
1078 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001079 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001080 fHWBounds.fScissorEnabled = false;
1081 }
1082 }
1083}
1084
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001085void GrGpuGL::eraseColorHelper(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001086 if (NULL == fCurrDrawState.fRenderTarget) {
1087 return;
1088 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001089 flushRenderTarget();
1090 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001091 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001092 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001093 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001094 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001095 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001096 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1097 GrColorUnpackG(color)/255.f,
1098 GrColorUnpackB(color)/255.f,
1099 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001100 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001101}
1102
1103void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001104 if (NULL == fCurrDrawState.fRenderTarget) {
1105 return;
1106 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001107 flushRenderTarget();
1108 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001109 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001110 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001111 }
1112 GR_GL(StencilMask(mask));
1113 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001114 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001115 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001116}
1117
bsalomon@google.comd302f142011-03-03 13:54:13 +00001118void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001119 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001120#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001121 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001122 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001123 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001124#else
1125 // we could just clear the clip bit but when we go through
1126 // angle a partial stencil mask will cause clears to be
1127 // turned into draws. Our contract on GrDrawTarget says that
1128 // changing the clip between stencil passes may or may not
1129 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001130 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001131#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001132 flushRenderTarget();
1133 flushScissor(&rect);
1134 GR_GL(StencilMask(clipStencilMask));
1135 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001136 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001137 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001138}
1139
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001140void GrGpuGL::forceRenderTargetFlushHelper() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001141 flushRenderTarget();
1142}
1143
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001144bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height,
1145 GrTexture::PixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001146 GrGLenum internalFormat; // we don't use this for glReadPixels
1147 GrGLenum format;
1148 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001149 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1150 return false;
1151 }
1152
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001153 if (NULL == fCurrDrawState.fRenderTarget) {
1154 return false;
1155 }
1156 flushRenderTarget();
1157
bsalomon@google.comd302f142011-03-03 13:54:13 +00001158 const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
1159
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001160 // the read rect is viewport-relative
1161 GrGLIRect readRect;
1162 readRect.setRelativeTo(glvp, left, top, width, height);
1163 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001164 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001165 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001166
1167 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1168 // API presents top-to-bottom
1169 {
1170 size_t stride = width * GrTexture::BytesPerPixel(config);
1171 GrAutoMalloc rowStorage(stride);
1172 void* tmp = rowStorage.get();
1173
1174 const int halfY = height >> 1;
1175 char* top = reinterpret_cast<char*>(buffer);
1176 char* bottom = top + (height - 1) * stride;
1177 for (int y = 0; y < halfY; y++) {
1178 memcpy(tmp, top, stride);
1179 memcpy(top, bottom, stride);
1180 memcpy(bottom, tmp, stride);
1181 top += stride;
1182 bottom -= stride;
1183 }
1184 }
1185 return true;
1186}
1187
1188void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001189
1190 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1191
reed@google.comac10a2d2010-12-22 21:39:39 +00001192 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1193 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001194 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001195 #if GR_COLLECT_STATS
1196 ++fStats.fRenderTargetChngCnt;
1197 #endif
1198 rt->setDirty(true);
1199 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001200 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1201 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001202 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1203 }
1204 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001205 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001206 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001207 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001208 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001209 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001210 fHWBounds.fViewportRect = vp;
1211 }
1212 }
1213}
1214
twiz@google.com0f31ca72011-03-18 17:38:11 +00001215GrGLenum gPrimitiveType2GLMode[] = {
1216 GR_GL_TRIANGLES,
1217 GR_GL_TRIANGLE_STRIP,
1218 GR_GL_TRIANGLE_FAN,
1219 GR_GL_POINTS,
1220 GR_GL_LINES,
1221 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001222};
1223
bsalomon@google.comd302f142011-03-03 13:54:13 +00001224#define SWAP_PER_DRAW 0
1225
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001226#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001227 #if GR_MAC_BUILD
1228 #include <AGL/agl.h>
1229 #elif GR_WIN32_BUILD
1230 void SwapBuf() {
1231 DWORD procID = GetCurrentProcessId();
1232 HWND hwnd = GetTopWindow(GetDesktopWindow());
1233 while(hwnd) {
1234 DWORD wndProcID = 0;
1235 GetWindowThreadProcessId(hwnd, &wndProcID);
1236 if(wndProcID == procID) {
1237 SwapBuffers(GetDC(hwnd));
1238 }
1239 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1240 }
1241 }
1242 #endif
1243#endif
1244
bsalomon@google.comffca4002011-02-22 20:34:01 +00001245void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001246 uint32_t startVertex,
1247 uint32_t startIndex,
1248 uint32_t vertexCount,
1249 uint32_t indexCount) {
1250 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1251
twiz@google.com0f31ca72011-03-18 17:38:11 +00001252 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001253
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001254 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1255 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1256
1257 // our setupGeometry better have adjusted this to zero since
1258 // DrawElements always draws from the begining of the arrays for idx 0.
1259 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001260
1261 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001262 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001263#if SWAP_PER_DRAW
1264 glFlush();
1265 #if GR_MAC_BUILD
1266 aglSwapBuffers(aglGetCurrentContext());
1267 int set_a_break_pt_here = 9;
1268 aglSwapBuffers(aglGetCurrentContext());
1269 #elif GR_WIN32_BUILD
1270 SwapBuf();
1271 int set_a_break_pt_here = 9;
1272 SwapBuf();
1273 #endif
1274#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001275}
1276
bsalomon@google.comffca4002011-02-22 20:34:01 +00001277void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001278 uint32_t startVertex,
1279 uint32_t vertexCount) {
1280 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1281
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001282 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1283
1284 // our setupGeometry better have adjusted this to zero.
1285 // DrawElements doesn't take an offset so we always adjus the startVertex.
1286 GrAssert(0 == startVertex);
1287
1288 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1289 // account for startVertex in the DrawElements case. So we always
1290 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001291 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001292#if SWAP_PER_DRAW
1293 glFlush();
1294 #if GR_MAC_BUILD
1295 aglSwapBuffers(aglGetCurrentContext());
1296 int set_a_break_pt_here = 9;
1297 aglSwapBuffers(aglGetCurrentContext());
1298 #elif GR_WIN32_BUILD
1299 SwapBuf();
1300 int set_a_break_pt_here = 9;
1301 SwapBuf();
1302 #endif
1303#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001304}
1305
reed@google.comac10a2d2010-12-22 21:39:39 +00001306void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1307 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1308
1309 if (NULL != rt && rt->needsResolve()) {
1310 GrAssert(kNone_MSFBO != fMSFBOType);
1311 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001312 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001313 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001314 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001315 rt->textureFBOID()));
1316 #if GR_COLLECT_STATS
1317 ++fStats.fRenderTargetChngCnt;
1318 #endif
1319 // make sure we go through set render target
1320 fHWDrawState.fRenderTarget = NULL;
1321
twiz@google.com0f31ca72011-03-18 17:38:11 +00001322 GrGLint left = 0;
1323 GrGLint right = texture->width();
reed@google.comac10a2d2010-12-22 21:39:39 +00001324 // we will have rendered to the top of the FBO.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001325 GrGLint top = texture->allocHeight();
1326 GrGLint bottom = texture->allocHeight() - texture->height();
reed@google.comac10a2d2010-12-22 21:39:39 +00001327 if (kApple_MSFBO == fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001328 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001329 GR_GL(Scissor(left, bottom, right-left, top-bottom));
twiz@google.com59a190b2011-03-14 21:23:01 +00001330 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001331 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001332 fHWBounds.fScissorEnabled = true;
1333 } else {
twiz@google.com59a190b2011-03-14 21:23:01 +00001334 GR_GL(BlitFramebuffer(left, bottom, right, top,
reed@google.comac10a2d2010-12-22 21:39:39 +00001335 left, bottom, right, top,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001336 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001337 }
1338 rt->setDirty(false);
1339
1340 }
1341}
1342
twiz@google.com0f31ca72011-03-18 17:38:11 +00001343static const GrGLenum grToGLStencilFunc[] = {
1344 GR_GL_ALWAYS, // kAlways_StencilFunc
1345 GR_GL_NEVER, // kNever_StencilFunc
1346 GR_GL_GREATER, // kGreater_StencilFunc
1347 GR_GL_GEQUAL, // kGEqual_StencilFunc
1348 GR_GL_LESS, // kLess_StencilFunc
1349 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1350 GR_GL_EQUAL, // kEqual_StencilFunc,
1351 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001352};
1353GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1354GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1355GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1356GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1357GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1358GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1359GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1360GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1361GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1362
twiz@google.com0f31ca72011-03-18 17:38:11 +00001363static const GrGLenum grToGLStencilOp[] = {
1364 GR_GL_KEEP, // kKeep_StencilOp
1365 GR_GL_REPLACE, // kReplace_StencilOp
1366 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1367 GR_GL_INCR, // kIncClamp_StencilOp
1368 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1369 GR_GL_DECR, // kDecClamp_StencilOp
1370 GR_GL_ZERO, // kZero_StencilOp
1371 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001372};
1373GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1374GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1375GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1376GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1377GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1378GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1379GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1380GR_STATIC_ASSERT(6 == kZero_StencilOp);
1381GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1382
reed@google.comac10a2d2010-12-22 21:39:39 +00001383void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001384 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001385
1386 // use stencil for clipping if clipping is enabled and the clip
1387 // has been written into the stencil.
1388 bool stencilClip = fClipState.fClipInStencil &&
1389 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001390 bool stencilChange = fHWStencilClip != stencilClip ||
1391 fHWDrawState.fStencilSettings != *settings ||
1392 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1393 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001394
1395 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001396
bsalomon@google.comd302f142011-03-03 13:54:13 +00001397 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1398 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001399
bsalomon@google.comd302f142011-03-03 13:54:13 +00001400 if (settings->isDisabled()) {
1401 if (stencilClip) {
1402 settings = &gClipStencilSettings;
1403 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001404 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001405
1406 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001407 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001408 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001409 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001410 #if GR_DEBUG
1411 if (!fStencilWrapOpsSupport) {
1412 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1413 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1414 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1415 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1416 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1417 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1418 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1419 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1420 }
1421 #endif
1422 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1423 GrAssert(stencilBits ||
1424 (GrStencilSettings::gDisabled ==
1425 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001426 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1427 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001428
1429 unsigned int frontRef = settings->fFrontFuncRef;
1430 unsigned int frontMask = settings->fFrontFuncMask;
1431 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001432 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001433
1434 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1435
1436 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1437 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1438 } else {
1439 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1440
1441 ConvertStencilFuncAndMask(settings->fFrontFunc,
1442 stencilClip,
1443 clipStencilMask,
1444 userStencilMask,
1445 &frontRef,
1446 &frontMask);
1447 frontWriteMask &= userStencilMask;
1448 }
1449 GrAssert(settings->fFrontFailOp >= 0 &&
1450 settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
1451 GrAssert(settings->fFrontPassOp >= 0 &&
1452 settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
1453 GrAssert(settings->fBackFailOp >= 0 &&
1454 settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
1455 GrAssert(settings->fBackPassOp >= 0 &&
1456 settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
1457 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001458 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001459
1460 unsigned int backRef = settings->fBackFuncRef;
1461 unsigned int backMask = settings->fBackFuncMask;
1462 unsigned int backWriteMask = settings->fBackWriteMask;
1463
1464
1465 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1466 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1467 backFunc = grToGLStencilFunc[settings->fBackFunc];
1468 } else {
1469 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1470 ConvertStencilFuncAndMask(settings->fBackFunc,
1471 stencilClip,
1472 clipStencilMask,
1473 userStencilMask,
1474 &backRef,
1475 &backMask);
1476 backWriteMask &= userStencilMask;
1477 }
1478
twiz@google.com0f31ca72011-03-18 17:38:11 +00001479 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1480 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1481 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1482 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1483 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001484 grToGLStencilOp[settings->fFrontPassOp],
1485 grToGLStencilOp[settings->fFrontPassOp]));
1486
twiz@google.com0f31ca72011-03-18 17:38:11 +00001487 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001488 grToGLStencilOp[settings->fBackPassOp],
1489 grToGLStencilOp[settings->fBackPassOp]));
1490 } else {
1491 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1492 GR_GL(StencilMask(frontWriteMask));
1493 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1494 grToGLStencilOp[settings->fFrontPassOp],
1495 grToGLStencilOp[settings->fFrontPassOp]));
1496 }
1497 }
1498 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001499 fHWStencilClip = stencilClip;
1500 }
1501}
1502
bsalomon@google.comffca4002011-02-22 20:34:01 +00001503bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001504
1505 // GrGpu::setupClipAndFlushState should have already checked this
1506 // and bailed if not true.
1507 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001508
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001509 for (int s = 0; s < kNumStages; ++s) {
1510 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001511
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001512 // bind texture and set sampler state
1513 if (usingTexture) {
1514 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001515
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001516 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001517 // if we created a rt/tex and rendered to it without using a
1518 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001519 // the last bound texture, but it needs resolving. So keep this
1520 // out of the "last != next" check.
1521 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001522
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001523 if (fHWDrawState.fTextures[s] != nextTexture) {
1524 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001525 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001526 #if GR_COLLECT_STATS
1527 ++fStats.fTextureChngCnt;
1528 #endif
1529 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1530 fHWDrawState.fTextures[s] = nextTexture;
1531 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001532
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001533 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001534 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001535 nextTexture->getTexParams();
1536 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001537
twiz@google.com0f31ca72011-03-18 17:38:11 +00001538 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1539 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001540 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001541 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001542 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001543 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001544
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001545 if (newTexParams.fFilter != oldTexParams.fFilter) {
1546 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001547 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1548 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001549 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001550 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1551 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001552 newTexParams.fFilter));
1553 }
1554 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1555 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001556 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1557 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001558 newTexParams.fWrapS));
1559 }
1560 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1561 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001562 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1563 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001564 newTexParams.fWrapT));
1565 }
1566 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001567
1568 // The texture matrix has to compensate for texture width/height
1569 // and NPOT-embedded-in-POT
1570 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001571 } else {
1572 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001573 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001574 }
1575 }
1576 }
1577
1578 flushRenderTarget();
1579
1580 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1581 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1582 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001583 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001584 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001585 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001586 }
1587 }
1588
bsalomon@google.comd302f142011-03-03 13:54:13 +00001589 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1590 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001591 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001592 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001593 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001594 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001595 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001596 }
1597 GR_GL(ColorMask(mask, mask, mask, mask));
1598 }
1599
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001600 if (GR_GL_SUPPORT_DESKTOP) {
1601 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1602 // smooth lines.
1603 if (fDirtyFlags.fRenderTargetChanged ||
1604 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1605 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1606 GrGLint msaa = 0;
1607 // only perform query if we know MSAA is supported.
1608 // calling on non-MSAA target caused a crash in one environment,
1609 // though I don't think it should.
1610 if (fAASamples[kHigh_AALevel]) {
1611 GR_GL_GetIntegerv(GR_GL_SAMPLE_BUFFERS, &msaa);
1612 }
1613 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1614 if (msaa) {
1615 GR_GL(Enable(GR_GL_MULTISAMPLE));
1616 } else {
1617 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1618 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001619 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001620 if (msaa) {
1621 GR_GL(Disable(GR_GL_MULTISAMPLE));
1622 }
1623 GR_GL(Disable(GR_GL_LINE_SMOOTH));
reed@google.comac10a2d2010-12-22 21:39:39 +00001624 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001625 }
1626 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001627
1628 bool blendOff = canDisableBlend();
1629 if (fHWBlendDisabled != blendOff) {
1630 if (blendOff) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001631 GR_GL(Disable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001632 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001633 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001634 }
1635 fHWBlendDisabled = blendOff;
1636 }
1637
1638 if (!blendOff) {
1639 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1640 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1641 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1642 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1643 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1644 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1645 }
bsalomon@google.com080773c2011-03-15 19:09:25 +00001646 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1647 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1648 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1649
1650 float c[] = {
1651 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1652 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1653 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1654 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1655 };
1656 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1657 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1658 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001659 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001660
bsalomon@google.comd302f142011-03-03 13:54:13 +00001661 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1662 switch (fCurrDrawState.fDrawFace) {
1663 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001664 GR_GL(Enable(GR_GL_CULL_FACE));
1665 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001666 break;
1667 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001668 GR_GL(Enable(GR_GL_CULL_FACE));
1669 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001670 break;
1671 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001672 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001673 break;
1674 default:
1675 GrCrash("Unknown draw face.");
1676 }
1677 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1678 }
1679
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001680#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001681 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001682 for (int s = 0; s < kNumStages; ++s) {
1683 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1684 NULL == fCurrDrawState.fRenderTarget ||
1685 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001686 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001687 fCurrDrawState.fRenderTarget);
1688 }
1689#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001690
reed@google.comac10a2d2010-12-22 21:39:39 +00001691 flushStencil();
1692
bsalomon@google.comd302f142011-03-03 13:54:13 +00001693 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001694 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001695 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001696}
1697
1698void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001699 if (fHWGeometryState.fVertexBuffer != buffer) {
1700 fHWGeometryState.fArrayPtrsDirty = true;
1701 fHWGeometryState.fVertexBuffer = buffer;
1702 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001703}
1704
1705void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1706 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1707 buffer == fGeometrySrc.fVertexBuffer));
1708
1709 if (fHWGeometryState.fVertexBuffer == buffer) {
1710 // deleting bound buffer does implied bind to 0
1711 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001712 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001713 }
1714}
1715
1716void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1717 fGeometrySrc.fIndexBuffer = buffer;
1718}
1719
1720void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1721 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1722 buffer == fGeometrySrc.fIndexBuffer));
1723
1724 if (fHWGeometryState.fIndexBuffer == buffer) {
1725 // deleting bound buffer does implied bind to 0
1726 fHWGeometryState.fIndexBuffer = NULL;
1727 }
1728}
1729
reed@google.comac10a2d2010-12-22 21:39:39 +00001730void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1731 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001732 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001733 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001734 }
1735 if (fHWDrawState.fRenderTarget == renderTarget) {
1736 fHWDrawState.fRenderTarget = NULL;
1737 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001738}
1739
1740void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001741 for (int s = 0; s < kNumStages; ++s) {
1742 if (fCurrDrawState.fTextures[s] == texture) {
1743 fCurrDrawState.fTextures[s] = NULL;
1744 }
1745 if (fHWDrawState.fTextures[s] == texture) {
1746 // deleting bound texture does implied bind to 0
1747 fHWDrawState.fTextures[s] = NULL;
1748 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001749 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001750}
1751
reed@google.comac10a2d2010-12-22 21:39:39 +00001752bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001753 GrGLenum* internalFormat,
1754 GrGLenum* format,
1755 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001756 switch (config) {
1757 case GrTexture::kRGBA_8888_PixelConfig:
1758 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001759 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001760 if (GR_GL_SUPPORT_ES) {
1761 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1762 // format for a BGRA is BGRA not RGBA (as on desktop)
1763 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1764 } else {
1765 *internalFormat = GR_GL_RGBA;
1766 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001767 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001768 break;
1769 case GrTexture::kRGB_565_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001770 *format = GR_GL_RGB;
1771 *internalFormat = GR_GL_RGB;
1772 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001773 break;
1774 case GrTexture::kRGBA_4444_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001775 *format = GR_GL_RGBA;
1776 *internalFormat = GR_GL_RGBA;
1777 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001778 break;
1779 case GrTexture::kIndex_8_PixelConfig:
1780 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001781 *format = GR_GL_PALETTE8_RGBA8;
1782 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001783 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001784 } else {
1785 return false;
1786 }
1787 break;
1788 case GrTexture::kAlpha_8_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001789 *format = GR_GL_ALPHA;
1790 *internalFormat = GR_GL_ALPHA;
1791 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001792 break;
1793 default:
1794 return false;
1795 }
1796 return true;
1797}
1798
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001799void GrGpuGL::setTextureUnit(int unit) {
1800 GrAssert(unit >= 0 && unit < kNumStages);
1801 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001802 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001803 fActiveTextureUnitIdx = unit;
1804 }
1805}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001806
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001807void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001808 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1809 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001810 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1811 }
1812}
1813
reed@google.comac10a2d2010-12-22 21:39:39 +00001814/* On ES the internalFormat and format must match for TexImage and we use
1815 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1816 decide the internalFormat. However, on ES internalFormat for
1817 RenderBufferStorage* has to be a specific format (not a base format like
1818 GL_RGBA).
1819 */
twiz@google.com0f31ca72011-03-18 17:38:11 +00001820bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001821 switch (config) {
1822 case GrTexture::kRGBA_8888_PixelConfig:
1823 case GrTexture::kRGBX_8888_PixelConfig:
1824 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001825 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001826 return true;
1827 } else {
1828 return false;
1829 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001830 case GrTexture::kRGB_565_PixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001831 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1832 // with FBO extension desktop GL has
1833 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001834 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001835 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001836 case GrTexture::kRGBA_4444_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001837 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001838 return true;
1839 default:
1840 return false;
1841 }
1842}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001843
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001844void GrGpuGL::resetDirtyFlags() {
1845 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1846}
1847
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001848void GrGpuGL::setBuffers(bool indexed,
1849 int* extraVertexOffset,
1850 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001851
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001852 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001853
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001854 GrGLVertexBuffer* vbuf;
1855 switch (fGeometrySrc.fVertexSrc) {
1856 case kBuffer_GeometrySrcType:
1857 *extraVertexOffset = 0;
1858 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1859 break;
1860 case kArray_GeometrySrcType:
1861 case kReserved_GeometrySrcType:
1862 finalizeReservedVertices();
1863 *extraVertexOffset = fCurrPoolStartVertex;
1864 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1865 break;
1866 default:
1867 vbuf = NULL; // suppress warning
1868 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001869 }
1870
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001871 GrAssert(NULL != vbuf);
1872 GrAssert(!vbuf->isLocked());
1873 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001874 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001875 fHWGeometryState.fArrayPtrsDirty = true;
1876 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001877 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001878
1879 if (indexed) {
1880 GrAssert(NULL != extraIndexOffset);
1881
1882 GrGLIndexBuffer* ibuf;
1883 switch (fGeometrySrc.fIndexSrc) {
1884 case kBuffer_GeometrySrcType:
1885 *extraIndexOffset = 0;
1886 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1887 break;
1888 case kArray_GeometrySrcType:
1889 case kReserved_GeometrySrcType:
1890 finalizeReservedIndices();
1891 *extraIndexOffset = fCurrPoolStartIndex;
1892 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1893 break;
1894 default:
1895 ibuf = NULL; // suppress warning
1896 GrCrash("Unknown geometry src type!");
1897 }
1898
1899 GrAssert(NULL != ibuf);
1900 GrAssert(!ibuf->isLocked());
1901 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001902 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001903 fHWGeometryState.fIndexBuffer = ibuf;
1904 }
1905 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001906}