blob: e94455100938039015f04193b12342d4176ad111 [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;
233 if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
234 fMSFBOType = kIMG_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000235 if (gPrintStartupSpew) {
236 GrPrintf("MSAA Support: IMG ES EXT.\n");
237 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000238 }
239 else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
240 fMSFBOType = kApple_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000241 if (gPrintStartupSpew) {
242 GrPrintf("MSAA Support: APPLE ES EXT.\n");
243 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000244 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000245 else if (GR_GL_SUPPORT_DESKTOP && (
246 (major >= 3) ||
reed@google.comac10a2d2010-12-22 21:39:39 +0000247 has_gl_extension("GL_ARB_framebuffer_object") ||
248 (has_gl_extension("GL_EXT_framebuffer_multisample") &&
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000249 has_gl_extension("GL_EXT_framebuffer_blit")))) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000250 fMSFBOType = kDesktop_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000251 if (gPrintStartupSpew) {
252 GrPrintf("MSAA Support: DESKTOP\n");
253 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000254 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000255 else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000256 if (gPrintStartupSpew) {
257 GrPrintf("MSAA Support: NONE\n");
258 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000259 }
260
261 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000262 GrGLint maxSamples;
263 GrGLenum maxSampleGetter = (kIMG_MSFBO == fMSFBOType) ?
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000264 GR_GL_MAX_SAMPLES_IMG :
265 GR_GL_MAX_SAMPLES;
reed@google.comac20fb92011-01-12 17:14:53 +0000266 GR_GL_GetIntegerv(maxSampleGetter, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000267 if (maxSamples > 1 ) {
268 fAASamples[kNone_AALevel] = 0;
269 fAASamples[kLow_AALevel] = GrMax(2,
270 GrFixedFloorToInt((GR_FixedHalf) *
271 maxSamples));
272 fAASamples[kMed_AALevel] = GrMax(2,
273 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
274 maxSamples));
275 fAASamples[kHigh_AALevel] = maxSamples;
276 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000277 if (gPrintStartupSpew) {
278 GrPrintf("\tMax Samples: %d\n", maxSamples);
279 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000280 }
281
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000282 if (GR_GL_SUPPORT_DESKTOP) {
283 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
284 has_gl_extension("GL_EXT_stencil_wrap");
285 } else {
286 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
287 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000288 if (gPrintStartupSpew) {
289 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
290 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000291
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000292 if (GR_GL_SUPPORT_DESKTOP) {
293 // we could also look for GL_ATI_separate_stencil extension or
294 // GL_EXT_stencil_two_side but they use different function signatures
295 // than GL2.0+ (and than each other).
296 fTwoSidedStencilSupport = (major >= 2);
297 // supported on GL 1.4 and higher or by extension
298 fStencilWrapOpsSupport = (major > 1) ||
299 ((1 == major) && (minor >= 4)) ||
300 has_gl_extension("GL_EXT_stencil_wrap");
301 } else {
302 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
303 // an ES1 extension.
304 fTwoSidedStencilSupport = (major >= 2);
305 // stencil wrap support is in ES2, ES1 requires extension.
306 fStencilWrapOpsSupport = (major > 1) ||
307 has_gl_extension("GL_OES_stencil_wrap");
308 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000309 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000310 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
311 (fTwoSidedStencilSupport ? "YES" : "NO"),
312 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000313 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000314
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000315 if (GR_GL_SUPPORT_DESKTOP) {
316 fRGBA8Renderbuffer = true;
317 } else {
318 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
319 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000320 if (gPrintStartupSpew) {
321 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
322 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000323
324
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000325 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000326 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000327 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
328 }
329 }
330
331 if (GR_GL_SUPPORT_DESKTOP) {
332 fBufferLockSupport = true; // we require VBO support and the desktop VBO
333 // extension includes glMapBuffer.
334 } else {
335 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
336 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000337
reed@google.comeeeb5a02010-12-23 15:12:59 +0000338 if (gPrintStartupSpew) {
339 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
340 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000341
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000342 if (GR_GL_SUPPORT_DESKTOP) {
343 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
344 fNPOTTextureTileSupport = true;
345 fNPOTTextureSupport = true;
346 } else {
347 fNPOTTextureTileSupport = false;
348 fNPOTTextureSupport = false;
349 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000350 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000351 if (major >= 2) {
352 fNPOTTextureSupport = true;
353 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
354 } else {
355 fNPOTTextureSupport =
356 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
357 fNPOTTextureTileSupport = false;
358 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000359 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000360
reed@google.comac10a2d2010-12-22 21:39:39 +0000361 ////////////////////////////////////////////////////////////////////////////
362 // Experiments to determine limitations that can't be queried. TODO: Make
363 // these a preprocess that generate some compile time constants.
364
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000365 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000366
twiz@google.com59a190b2011-03-14 21:23:01 +0000367 bool simpleFBOSuccess = fbo_test(128, 128);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000368 if (gPrintStartupSpew) {
369 if (!simpleFBOSuccess) {
370 GrPrintf("FBO Sanity Test: FAILED\n");
371 } else {
372 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000373 }
374 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000375 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000376
reed@google.comac10a2d2010-12-22 21:39:39 +0000377 /* Experimentation has found that some GLs that support NPOT textures
378 do not support FBOs with a NPOT texture. They report "unsupported" FBO
379 status. I don't know how to explicitly query for this. Do an
380 experiment. Note they may support NPOT with a renderbuffer but not a
381 texture. Presumably, the implementation bloats the renderbuffer
382 internally to the next POT.
383 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000384 bool fNPOTRenderTargetSupport = false;
385 if (fNPOTTextureSupport) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000386 fNPOTRenderTargetSupport = fbo_test(200, 200);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000387 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000388
bsalomon@google.com0748f212011-02-01 22:56:16 +0000389 if (gPrintStartupSpew) {
390 if (fNPOTTextureSupport) {
391 GrPrintf("NPOT textures supported\n");
392 if (fNPOTTextureTileSupport) {
393 GrPrintf("NPOT texture tiling supported\n");
394 } else {
395 GrPrintf("NPOT texture tiling NOT supported\n");
396 }
397 if (fNPOTRenderTargetSupport) {
398 GrPrintf("NPOT render targets supported\n");
399 } else {
400 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000401 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000402 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000403 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000404 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000405 }
406
reed@google.comac10a2d2010-12-22 21:39:39 +0000407 /* The iPhone 4 has a restriction that for an FBO with texture color
408 attachment with height <= 8 then the width must be <= height. Here
409 we look for such a limitation.
410 */
411 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000412 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000413 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000414
reed@google.comeeeb5a02010-12-23 15:12:59 +0000415 if (gPrintStartupSpew) {
416 GrPrintf("Small height FBO texture experiments\n");
417 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000418
twiz@google.com0f31ca72011-03-18 17:38:11 +0000419 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
420 GrGLuint w = maxRenderSize;
421 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000422 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000423 if (gPrintStartupSpew) {
424 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
425 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000426 fMinRenderTargetHeight = i;
427 break;
428 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000429 if (gPrintStartupSpew) {
430 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
431 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000432 }
433 }
434 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
435
reed@google.comeeeb5a02010-12-23 15:12:59 +0000436 if (gPrintStartupSpew) {
437 GrPrintf("Small width FBO texture experiments\n");
438 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000439 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000440 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
441 GrGLuint w = i;
442 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000443 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000444 if (gPrintStartupSpew) {
445 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
446 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000447 fMinRenderTargetWidth = i;
448 break;
449 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000450 if (gPrintStartupSpew) {
451 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
452 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000453 }
454 }
455 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
456
twiz@google.com0f31ca72011-03-18 17:38:11 +0000457 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000458}
459
460GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000461}
462
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000463void GrGpuGL::resetContext() {
464 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000465 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000466 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000467
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000468 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000469 GR_GL(Disable(GR_GL_DEPTH_TEST));
470 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000471
twiz@google.com0f31ca72011-03-18 17:38:11 +0000472 GR_GL(Disable(GR_GL_CULL_FACE));
473 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000474 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000475
twiz@google.com0f31ca72011-03-18 17:38:11 +0000476 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000477 if (GR_GL_SUPPORT_DESKTOP) {
478 GR_GL(Disable(GR_GL_LINE_SMOOTH));
479 GR_GL(Disable(GR_GL_POINT_SMOOTH));
480 GR_GL(Disable(GR_GL_MULTISAMPLE));
481 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000482
twiz@google.com0f31ca72011-03-18 17:38:11 +0000483 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000484 fHWDrawState.fFlagBits = 0;
485
reed@google.comac10a2d2010-12-22 21:39:39 +0000486 // we only ever use lines in hairline mode
487 GR_GL(LineWidth(1));
488
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000489 // invalid
490 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000491
reed@google.comac10a2d2010-12-22 21:39:39 +0000492 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000493 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
494 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000495
496 fHWDrawState.fBlendConstant = 0x00000000;
497 GR_GL(BlendColor(0,0,0,0));
498
reed@google.comac10a2d2010-12-22 21:39:39 +0000499 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000500
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000501 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000502
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000503 for (int s = 0; s < kNumStages; ++s) {
504 fHWDrawState.fTextures[s] = NULL;
505 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
506 -GR_ScalarMax,
507 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000508
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000509 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000510 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000511
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000512 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000513 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000514 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000515 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000516
bsalomon@google.comd302f142011-03-03 13:54:13 +0000517 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000518 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000519 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000520
521 fHWGeometryState.fIndexBuffer = NULL;
522 fHWGeometryState.fVertexBuffer = NULL;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000523 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
524 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000525 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000526
twiz@google.com0f31ca72011-03-18 17:38:11 +0000527 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000528 fHWDrawState.fRenderTarget = NULL;
529}
530
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000531GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
reed@google.comac10a2d2010-12-22 21:39:39 +0000532 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000533 int stencilBits,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000534 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000535 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000536 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
537 rtIDs.fStencilRenderbufferID = 0;
538 rtIDs.fMSColorRenderbufferID = 0;
539 rtIDs.fTexFBOID = 0;
540 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000541 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000542
543 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000544 viewport.fLeft = 0;
545 viewport.fBottom = 0;
546 viewport.fWidth = width;
547 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000548
twiz@google.com0f31ca72011-03-18 17:38:11 +0000549 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
550 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000551
bsalomon@google.com1da07462011-03-10 14:51:57 +0000552 return new GrGLRenderTarget(rtIDs, NULL, stencilBits, viewport, NULL, this);
reed@google.comac10a2d2010-12-22 21:39:39 +0000553}
554
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000555GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000556
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000557 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000558
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000559 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000560 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
561 rtIDs.fMSColorRenderbufferID = 0;
562 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000563
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000564 GrGLIRect viewport;
565 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000566 GrGLuint stencilBits;
567 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000568
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000569 rtIDs.fOwnIDs = false;
570
bsalomon@google.com1da07462011-03-10 14:51:57 +0000571 return new GrGLRenderTarget(rtIDs, NULL, stencilBits, viewport, NULL, this);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000572}
573
bsalomon@google.com5782d712011-01-21 21:03:59 +0000574///////////////////////////////////////////////////////////////////////////////
575
twiz@google.com0f31ca72011-03-18 17:38:11 +0000576static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000577
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000578struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000579 GrGLenum fEnum;
580 GrGLuint fBits;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000581};
582
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000583const StencilFormat* GrGLStencilFormats() {
584 // defines stencil formats from more to less preferred
585 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000586 {GR_GL_STENCIL_INDEX8, 8},
587 {GR_GL_STENCIL_INDEX16, 16},
588 {GR_GL_DEPTH24_STENCIL8, 8},
589 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000590 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS},
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000591 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000592 {0, 0}
593 };
594
595 static const StencilFormat esStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000596 {GR_GL_STENCIL_INDEX8, 8},
597 {GR_GL_DEPTH24_STENCIL8, 8},
598 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000599 {0, 0}
600 };
601
602 if (GR_GL_SUPPORT_DESKTOP) {
603 return desktopStencilFormats;
604 } else {
605 return esStencilFormats;
606 }
607}
608
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000609// good to set a break-point here to know when createTexture fails
610static GrTexture* return_null_texture() {
611// GrAssert(!"null texture");
612 return NULL;
613}
614
615#if GR_DEBUG
616static size_t as_size_t(int x) {
617 return x;
618}
619#endif
620
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000621GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
622 const void* srcData,
623 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000624
625#if GR_COLLECT_STATS
626 ++fStats.fTextureCreateCnt;
627#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000628
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000629 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000630
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000631 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000632 GR_GL_NEAREST,
633 GR_GL_CLAMP_TO_EDGE,
634 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000635 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000636
reed@google.comac10a2d2010-12-22 21:39:39 +0000637 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000638 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000639
640 glDesc.fContentWidth = desc.fWidth;
641 glDesc.fContentHeight = desc.fHeight;
642 glDesc.fAllocWidth = desc.fWidth;
643 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000644 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000645 glDesc.fFormat = desc.fFormat;
646
647 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
648 if (!canBeTexture(desc.fFormat,
649 &internalFormat,
650 &glDesc.fUploadFormat,
651 &glDesc.fUploadType)) {
652 return return_null_texture();
653 }
654
655 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000656 GrGLint samples = fAASamples[desc.fAALevel];
reed@google.comac10a2d2010-12-22 21:39:39 +0000657 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
658 GrPrintf("AA RT requested but not supported on this platform.");
659 }
660
661 GR_GL(GenTextures(1, &glDesc.fTextureID));
662 if (!glDesc.fTextureID) {
663 return return_null_texture();
664 }
665
666 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
667
668 /*
669 * check if our srcData has extra bytes past each row. If so, we need
670 * to trim those off here, since GL doesn't let us pass the rowBytes as
671 * a parameter to glTexImage2D
672 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000673 if (GR_GL_SUPPORT_DESKTOP) {
674 if (srcData) {
675 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
676 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000677 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000678 } else {
679 GrAutoSMalloc<128 * 128> trimStorage;
680 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
681 if (srcData && (trimRowBytes < rowBytes)) {
682 size_t trimSize = desc.fHeight * trimRowBytes;
683 trimStorage.realloc(trimSize);
684 // now copy the data into our new storage, skipping the trailing bytes
685 const char* src = (const char*)srcData;
686 char* dst = (char*)trimStorage.get();
687 for (uint32_t y = 0; y < desc.fHeight; y++) {
688 memcpy(dst, src, trimRowBytes);
689 src += rowBytes;
690 dst += trimRowBytes;
691 }
692 // now point srcData to our trimmed version
693 srcData = trimStorage.get();
694 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000695 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000696
reed@google.comac10a2d2010-12-22 21:39:39 +0000697 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000698 if (!this->npotRenderTargetSupport()) {
699 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
700 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
701 }
702
reed@google.comac10a2d2010-12-22 21:39:39 +0000703 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
704 glDesc.fAllocWidth);
705 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
706 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000707 } else if (!this->npotTextureSupport()) {
708 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
709 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000710 }
711
twiz@google.com0f31ca72011-03-18 17:38:11 +0000712 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
713 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
714 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000715 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000716 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
717 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000718 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000719 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
720 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000721 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000722 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
723 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000724 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000725
twiz@google.com0f31ca72011-03-18 17:38:11 +0000726 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000727 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
728 supports8BitPalette()) {
729 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
730 GrAssert(desc.fWidth == glDesc.fAllocWidth);
731 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000732 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
733 kColorTableSize;
734 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000735 glDesc.fAllocWidth, glDesc.fAllocHeight,
736 0, imageSize, srcData));
737 GrGL_RestoreResetRowLength();
738 } else {
739 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
740 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000741 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000742 glDesc.fAllocWidth, glDesc.fAllocHeight,
743 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000744 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000745 desc.fHeight, glDesc.fUploadFormat,
746 glDesc.fUploadType, srcData));
747 GrGL_RestoreResetRowLength();
748
749 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
750 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
751 uint32_t maxTexels = extraW * extraH;
752 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
753 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
754
755 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
756
757 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
758 if (extraH) {
759 uint8_t* lastRowStart = (uint8_t*) srcData +
760 (desc.fHeight - 1) * rowSize;
761 uint8_t* extraRowStart = (uint8_t*)texels.get();
762
763 for (uint32_t i = 0; i < extraH; ++i) {
764 memcpy(extraRowStart, lastRowStart, rowSize);
765 extraRowStart += rowSize;
766 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000767 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000768 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
769 texels.get()));
770 }
771 if (extraW) {
772 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
773 uint8_t* extraTexel = (uint8_t*)texels.get();
774 for (uint32_t j = 0; j < desc.fHeight; ++j) {
775 for (uint32_t i = 0; i < extraW; ++i) {
776 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
777 extraTexel += glDesc.fUploadByteCount;
778 }
779 edgeTexel += rowSize;
780 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000781 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000782 desc.fHeight, glDesc.fUploadFormat,
783 glDesc.fUploadType, texels.get()));
784 }
785 if (extraW && extraH) {
786 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
787 - glDesc.fUploadByteCount;
788 uint8_t* extraTexel = (uint8_t*)texels.get();
789 for (uint32_t i = 0; i < extraW*extraH; ++i) {
790 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
791 extraTexel += glDesc.fUploadByteCount;
792 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000793 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000794 extraW, extraH, glDesc.fUploadFormat,
795 glDesc.fUploadType, texels.get()));
796 }
797
798 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000799 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000800 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
801 glDesc.fUploadType, srcData));
802 GrGL_RestoreResetRowLength();
803 }
804 }
805
806 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
807
808 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
809 rtIDs.fStencilRenderbufferID = 0;
810 rtIDs.fMSColorRenderbufferID = 0;
811 rtIDs.fRTFBOID = 0;
812 rtIDs.fTexFBOID = 0;
813 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000814 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000815
816 if (renderTarget) {
817#if GR_COLLECT_STATS
818 ++fStats.fRenderTargetCreateCnt;
819#endif
820 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000821 GrGLenum status;
822 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000823
824 // If need have both RT flag and srcData we have
825 // to invert the data before uploading because FBO
826 // will be rendered bottom up
827 GrAssert(NULL == srcData);
828 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
829
twiz@google.com59a190b2011-03-14 21:23:01 +0000830 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000831 GrAssert(rtIDs.fTexFBOID);
832
833 // If we are using multisampling and any extension other than the IMG
834 // one we will create two FBOs. We render to one and then resolve to
835 // the texture bound to the other. The IMG extension does an implicit
836 // resolve.
837 if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000838 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000839 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000840 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000841 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
842 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000843 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000844 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000845 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
846 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000847 return return_null_texture();
848 }
849 } else {
850 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
851 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000852 if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000853 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000854 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000855 }
856
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000857 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000858 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000859 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000860 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000861
twiz@google.com0f31ca72011-03-18 17:38:11 +0000862 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000863
864 const StencilFormat* stencilFormats = GrGLStencilFormats();
865 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000866 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000867 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000868 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000869 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000870 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000871 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000872 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000873 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000874 glDesc.fAllocWidth,
875 glDesc.fAllocHeight));
876 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000877 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000878 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000879 glDesc.fAllocWidth,
880 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000881 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000882 err = GrGLGetGLInterface()->fGetError();
883 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000884 continue;
885 }
886 }
887 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
888 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000889 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000890 rtIDs.fMSColorRenderbufferID));
891 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000892 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000893 samples,
894 msColorRenderbufferFormat,
895 glDesc.fAllocWidth,
896 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000897 err = GrGLGetGLInterface()->fGetError();
898 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000899 continue;
900 }
901 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000902 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000903
904#if GR_COLLECT_STATS
905 ++fStats.fRenderTargetChngCnt;
906#endif
907 if (kIMG_MSFBO == fMSFBOType && samples > 1) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000908 GR_GL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER,
909 GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000910 GR_GL_TEXTURE_2D,
twiz@google.com59a190b2011-03-14 21:23:01 +0000911 glDesc.fTextureID,
912 0,
913 samples));
reed@google.comac10a2d2010-12-22 21:39:39 +0000914
915 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000916 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
917 GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000918 GR_GL_TEXTURE_2D,
twiz@google.com59a190b2011-03-14 21:23:01 +0000919 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000920 }
921 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000922 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
923 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000924 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
925 status, desc.fWidth, desc.fHeight);
926 continue;
927 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000928 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000929 #if GR_COLLECT_STATS
930 ++fStats.fRenderTargetChngCnt;
931 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000932 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
933 GR_GL_COLOR_ATTACHMENT0,
934 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000935 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000936
937 }
938 if (rtIDs.fStencilRenderbufferID) {
939 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000940 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
941 GR_GL_STENCIL_ATTACHMENT,
942 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000943 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000944 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000945 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000946
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000947 if (GR_GL_SUPPORT_DESKTOP) {
948 // On some implementations you have to be bound as DEPTH_STENCIL.
949 // (Even binding to DEPTH and STENCIL separately with the same
950 // buffer doesn't work.)
951 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000952 status != GR_GL_FRAMEBUFFER_COMPLETE) {
953 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
954 GR_GL_STENCIL_ATTACHMENT,
955 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000956 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000957 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
958 GR_GL_DEPTH_STENCIL_ATTACHMENT,
959 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000960 rtIDs.fStencilRenderbufferID));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000961 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000962 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000963 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000964 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000965 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
966 status, desc.fWidth, desc.fHeight);
967 if (GR_GL_SUPPORT_DESKTOP) {
968 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000969 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
970 GR_GL_DEPTH_STENCIL_ATTACHMENT,
971 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000972 0));
973 }
974 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000975 continue;
976 }
977 // we're successful!
978 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000979 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000980 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000981 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000982 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000983 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000984 }
985 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000986 break;
987 }
988 if (failed) {
989 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000990 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000991 }
992 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000993 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000994 }
995 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000996 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000997 }
998 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000999 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001000 }
1001 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1002 return return_null_texture();
1003 }
1004 }
1005#ifdef TRACE_TEXTURE_CREATION
1006 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1007 tex->fTextureID, width, height, tex->fUploadByteCount);
1008#endif
bsalomon@google.comda96ea02010-12-23 16:53:57 +00001009 GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, DEFAULT_PARAMS, this);
reed@google.comac10a2d2010-12-22 21:39:39 +00001010
1011 if (0 != rtIDs.fTexFBOID) {
1012 GrRenderTarget* rt = tex->asRenderTarget();
1013 // We've messed with FBO state but may not have set the correct viewport
1014 // so just dirty the rendertarget state to force a resend.
1015 fHWDrawState.fRenderTarget = NULL;
1016
1017 // clear the new stencil buffer if we have one
1018 if (!(desc.fFlags & kNoPathRendering_TextureFlag)) {
1019 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1020 fCurrDrawState.fRenderTarget = rt;
1021 eraseStencil(0, ~0);
1022 fCurrDrawState.fRenderTarget = rtSave;
1023 }
1024 }
1025 return tex;
1026}
1027
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001028GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001029 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001030 GR_GL(GenBuffers(1, &id));
1031 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001032 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001033 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001034 GrGLClearErr();
1035 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001036 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1037 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1038 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001039 GR_GL(DeleteBuffers(1, &id));
1040 // deleting bound buffer does implicit bind to 0
1041 fHWGeometryState.fVertexBuffer = NULL;
1042 return NULL;
1043 }
1044 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this,
1045 size, dynamic);
1046 fHWGeometryState.fVertexBuffer = vertexBuffer;
1047 return vertexBuffer;
1048 }
1049 return NULL;
1050}
1051
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001052GrIndexBuffer* GrGpuGL::createIndexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001053 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001054 GR_GL(GenBuffers(1, &id));
1055 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001056 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001057 GrGLClearErr();
1058 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001059 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1060 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1061 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001062 GR_GL(DeleteBuffers(1, &id));
1063 // deleting bound buffer does implicit bind to 0
1064 fHWGeometryState.fIndexBuffer = NULL;
1065 return NULL;
1066 }
1067 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this,
1068 size, dynamic);
1069 fHWGeometryState.fIndexBuffer = indexBuffer;
1070 return indexBuffer;
1071 }
1072 return NULL;
1073}
1074
reed@google.comac10a2d2010-12-22 21:39:39 +00001075void GrGpuGL::flushScissor(const GrIRect* rect) {
1076 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001077 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001078 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001079
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001080 GrGLIRect scissor;
1081 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001082 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001083 rect->width(), rect->height());
1084 if (scissor.contains(vp)) {
1085 rect = NULL;
1086 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001087 }
1088
1089 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001090 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001091 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001092 fHWBounds.fScissorRect = scissor;
1093 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001095 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001096 fHWBounds.fScissorEnabled = true;
1097 }
1098 } else {
1099 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001100 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001101 fHWBounds.fScissorEnabled = false;
1102 }
1103 }
1104}
1105
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001106void GrGpuGL::eraseColorHelper(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001107 if (NULL == fCurrDrawState.fRenderTarget) {
1108 return;
1109 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001110 flushRenderTarget();
1111 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001112 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001113 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001114 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001115 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001116 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001117 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1118 GrColorUnpackG(color)/255.f,
1119 GrColorUnpackB(color)/255.f,
1120 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001121 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001122}
1123
1124void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001125 if (NULL == fCurrDrawState.fRenderTarget) {
1126 return;
1127 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001128 flushRenderTarget();
1129 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001130 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001131 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001132 }
1133 GR_GL(StencilMask(mask));
1134 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001135 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001136 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001137}
1138
bsalomon@google.comd302f142011-03-03 13:54:13 +00001139void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001140 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001141#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001142 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001143 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001144 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001145#else
1146 // we could just clear the clip bit but when we go through
1147 // angle a partial stencil mask will cause clears to be
1148 // turned into draws. Our contract on GrDrawTarget says that
1149 // changing the clip between stencil passes may or may not
1150 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001151 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001152#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001153 flushRenderTarget();
1154 flushScissor(&rect);
1155 GR_GL(StencilMask(clipStencilMask));
1156 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001157 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001158 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001159}
1160
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001161void GrGpuGL::forceRenderTargetFlushHelper() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001162 flushRenderTarget();
1163}
1164
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001165bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height,
1166 GrTexture::PixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001167 GrGLenum internalFormat; // we don't use this for glReadPixels
1168 GrGLenum format;
1169 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001170 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1171 return false;
1172 }
1173
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001174 if (NULL == fCurrDrawState.fRenderTarget) {
1175 return false;
1176 }
1177 flushRenderTarget();
1178
bsalomon@google.comd302f142011-03-03 13:54:13 +00001179 const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
1180
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001181 // the read rect is viewport-relative
1182 GrGLIRect readRect;
1183 readRect.setRelativeTo(glvp, left, top, width, height);
1184 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001185 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001186 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001187
1188 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1189 // API presents top-to-bottom
1190 {
1191 size_t stride = width * GrTexture::BytesPerPixel(config);
1192 GrAutoMalloc rowStorage(stride);
1193 void* tmp = rowStorage.get();
1194
1195 const int halfY = height >> 1;
1196 char* top = reinterpret_cast<char*>(buffer);
1197 char* bottom = top + (height - 1) * stride;
1198 for (int y = 0; y < halfY; y++) {
1199 memcpy(tmp, top, stride);
1200 memcpy(top, bottom, stride);
1201 memcpy(bottom, tmp, stride);
1202 top += stride;
1203 bottom -= stride;
1204 }
1205 }
1206 return true;
1207}
1208
1209void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001210
1211 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1212
reed@google.comac10a2d2010-12-22 21:39:39 +00001213 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1214 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001215 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001216 #if GR_COLLECT_STATS
1217 ++fStats.fRenderTargetChngCnt;
1218 #endif
1219 rt->setDirty(true);
1220 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001221 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1222 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001223 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1224 }
1225 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001226 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001227 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001228 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001229 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001230 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001231 fHWBounds.fViewportRect = vp;
1232 }
1233 }
1234}
1235
twiz@google.com0f31ca72011-03-18 17:38:11 +00001236GrGLenum gPrimitiveType2GLMode[] = {
1237 GR_GL_TRIANGLES,
1238 GR_GL_TRIANGLE_STRIP,
1239 GR_GL_TRIANGLE_FAN,
1240 GR_GL_POINTS,
1241 GR_GL_LINES,
1242 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001243};
1244
bsalomon@google.comd302f142011-03-03 13:54:13 +00001245#define SWAP_PER_DRAW 0
1246
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001247#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001248 #if GR_MAC_BUILD
1249 #include <AGL/agl.h>
1250 #elif GR_WIN32_BUILD
1251 void SwapBuf() {
1252 DWORD procID = GetCurrentProcessId();
1253 HWND hwnd = GetTopWindow(GetDesktopWindow());
1254 while(hwnd) {
1255 DWORD wndProcID = 0;
1256 GetWindowThreadProcessId(hwnd, &wndProcID);
1257 if(wndProcID == procID) {
1258 SwapBuffers(GetDC(hwnd));
1259 }
1260 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1261 }
1262 }
1263 #endif
1264#endif
1265
bsalomon@google.comffca4002011-02-22 20:34:01 +00001266void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001267 uint32_t startVertex,
1268 uint32_t startIndex,
1269 uint32_t vertexCount,
1270 uint32_t indexCount) {
1271 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1272
twiz@google.com0f31ca72011-03-18 17:38:11 +00001273 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001274
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001275 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1276 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1277
1278 // our setupGeometry better have adjusted this to zero since
1279 // DrawElements always draws from the begining of the arrays for idx 0.
1280 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001281
1282 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001283 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001284#if SWAP_PER_DRAW
1285 glFlush();
1286 #if GR_MAC_BUILD
1287 aglSwapBuffers(aglGetCurrentContext());
1288 int set_a_break_pt_here = 9;
1289 aglSwapBuffers(aglGetCurrentContext());
1290 #elif GR_WIN32_BUILD
1291 SwapBuf();
1292 int set_a_break_pt_here = 9;
1293 SwapBuf();
1294 #endif
1295#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001296}
1297
bsalomon@google.comffca4002011-02-22 20:34:01 +00001298void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001299 uint32_t startVertex,
1300 uint32_t vertexCount) {
1301 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1302
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001303 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1304
1305 // our setupGeometry better have adjusted this to zero.
1306 // DrawElements doesn't take an offset so we always adjus the startVertex.
1307 GrAssert(0 == startVertex);
1308
1309 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1310 // account for startVertex in the DrawElements case. So we always
1311 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001312 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001313#if SWAP_PER_DRAW
1314 glFlush();
1315 #if GR_MAC_BUILD
1316 aglSwapBuffers(aglGetCurrentContext());
1317 int set_a_break_pt_here = 9;
1318 aglSwapBuffers(aglGetCurrentContext());
1319 #elif GR_WIN32_BUILD
1320 SwapBuf();
1321 int set_a_break_pt_here = 9;
1322 SwapBuf();
1323 #endif
1324#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001325}
1326
reed@google.comac10a2d2010-12-22 21:39:39 +00001327void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1328 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1329
1330 if (NULL != rt && rt->needsResolve()) {
1331 GrAssert(kNone_MSFBO != fMSFBOType);
1332 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001333 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001334 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001335 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001336 rt->textureFBOID()));
1337 #if GR_COLLECT_STATS
1338 ++fStats.fRenderTargetChngCnt;
1339 #endif
1340 // make sure we go through set render target
1341 fHWDrawState.fRenderTarget = NULL;
1342
twiz@google.com0f31ca72011-03-18 17:38:11 +00001343 GrGLint left = 0;
1344 GrGLint right = texture->width();
reed@google.comac10a2d2010-12-22 21:39:39 +00001345 // we will have rendered to the top of the FBO.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001346 GrGLint top = texture->allocHeight();
1347 GrGLint bottom = texture->allocHeight() - texture->height();
reed@google.comac10a2d2010-12-22 21:39:39 +00001348 if (kApple_MSFBO == fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001349 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001350 GR_GL(Scissor(left, bottom, right-left, top-bottom));
twiz@google.com59a190b2011-03-14 21:23:01 +00001351 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001352 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001353 fHWBounds.fScissorEnabled = true;
1354 } else {
twiz@google.com59a190b2011-03-14 21:23:01 +00001355 GR_GL(BlitFramebuffer(left, bottom, right, top,
reed@google.comac10a2d2010-12-22 21:39:39 +00001356 left, bottom, right, top,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001357 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001358 }
1359 rt->setDirty(false);
1360
1361 }
1362}
1363
twiz@google.com0f31ca72011-03-18 17:38:11 +00001364static const GrGLenum grToGLStencilFunc[] = {
1365 GR_GL_ALWAYS, // kAlways_StencilFunc
1366 GR_GL_NEVER, // kNever_StencilFunc
1367 GR_GL_GREATER, // kGreater_StencilFunc
1368 GR_GL_GEQUAL, // kGEqual_StencilFunc
1369 GR_GL_LESS, // kLess_StencilFunc
1370 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1371 GR_GL_EQUAL, // kEqual_StencilFunc,
1372 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001373};
1374GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1375GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1376GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1377GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1378GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1379GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1380GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1381GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1382GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1383
twiz@google.com0f31ca72011-03-18 17:38:11 +00001384static const GrGLenum grToGLStencilOp[] = {
1385 GR_GL_KEEP, // kKeep_StencilOp
1386 GR_GL_REPLACE, // kReplace_StencilOp
1387 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1388 GR_GL_INCR, // kIncClamp_StencilOp
1389 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1390 GR_GL_DECR, // kDecClamp_StencilOp
1391 GR_GL_ZERO, // kZero_StencilOp
1392 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001393};
1394GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1395GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1396GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1397GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1398GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1399GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1400GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1401GR_STATIC_ASSERT(6 == kZero_StencilOp);
1402GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1403
reed@google.comac10a2d2010-12-22 21:39:39 +00001404void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001405 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001406
1407 // use stencil for clipping if clipping is enabled and the clip
1408 // has been written into the stencil.
1409 bool stencilClip = fClipState.fClipInStencil &&
1410 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001411 bool stencilChange = fHWStencilClip != stencilClip ||
1412 fHWDrawState.fStencilSettings != *settings ||
1413 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1414 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001415
1416 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001417
bsalomon@google.comd302f142011-03-03 13:54:13 +00001418 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1419 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001420
bsalomon@google.comd302f142011-03-03 13:54:13 +00001421 if (settings->isDisabled()) {
1422 if (stencilClip) {
1423 settings = &gClipStencilSettings;
1424 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001425 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001426
1427 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001428 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001429 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001430 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001431 #if GR_DEBUG
1432 if (!fStencilWrapOpsSupport) {
1433 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1434 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1435 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1436 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1437 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1438 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1439 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1440 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1441 }
1442 #endif
1443 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1444 GrAssert(stencilBits ||
1445 (GrStencilSettings::gDisabled ==
1446 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001447 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1448 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001449
1450 unsigned int frontRef = settings->fFrontFuncRef;
1451 unsigned int frontMask = settings->fFrontFuncMask;
1452 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001453 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001454
1455 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1456
1457 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1458 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1459 } else {
1460 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1461
1462 ConvertStencilFuncAndMask(settings->fFrontFunc,
1463 stencilClip,
1464 clipStencilMask,
1465 userStencilMask,
1466 &frontRef,
1467 &frontMask);
1468 frontWriteMask &= userStencilMask;
1469 }
1470 GrAssert(settings->fFrontFailOp >= 0 &&
1471 settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
1472 GrAssert(settings->fFrontPassOp >= 0 &&
1473 settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
1474 GrAssert(settings->fBackFailOp >= 0 &&
1475 settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
1476 GrAssert(settings->fBackPassOp >= 0 &&
1477 settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
1478 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001479 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001480
1481 unsigned int backRef = settings->fBackFuncRef;
1482 unsigned int backMask = settings->fBackFuncMask;
1483 unsigned int backWriteMask = settings->fBackWriteMask;
1484
1485
1486 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1487 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1488 backFunc = grToGLStencilFunc[settings->fBackFunc];
1489 } else {
1490 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1491 ConvertStencilFuncAndMask(settings->fBackFunc,
1492 stencilClip,
1493 clipStencilMask,
1494 userStencilMask,
1495 &backRef,
1496 &backMask);
1497 backWriteMask &= userStencilMask;
1498 }
1499
twiz@google.com0f31ca72011-03-18 17:38:11 +00001500 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1501 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1502 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1503 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1504 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001505 grToGLStencilOp[settings->fFrontPassOp],
1506 grToGLStencilOp[settings->fFrontPassOp]));
1507
twiz@google.com0f31ca72011-03-18 17:38:11 +00001508 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001509 grToGLStencilOp[settings->fBackPassOp],
1510 grToGLStencilOp[settings->fBackPassOp]));
1511 } else {
1512 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1513 GR_GL(StencilMask(frontWriteMask));
1514 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1515 grToGLStencilOp[settings->fFrontPassOp],
1516 grToGLStencilOp[settings->fFrontPassOp]));
1517 }
1518 }
1519 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001520 fHWStencilClip = stencilClip;
1521 }
1522}
1523
bsalomon@google.comffca4002011-02-22 20:34:01 +00001524bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001525
1526 // GrGpu::setupClipAndFlushState should have already checked this
1527 // and bailed if not true.
1528 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001529
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001530 for (int s = 0; s < kNumStages; ++s) {
1531 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001532
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001533 // bind texture and set sampler state
1534 if (usingTexture) {
1535 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001536
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001537 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001538 // if we created a rt/tex and rendered to it without using a
1539 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001540 // the last bound texture, but it needs resolving. So keep this
1541 // out of the "last != next" check.
1542 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001543
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001544 if (fHWDrawState.fTextures[s] != nextTexture) {
1545 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001546 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001547 #if GR_COLLECT_STATS
1548 ++fStats.fTextureChngCnt;
1549 #endif
1550 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1551 fHWDrawState.fTextures[s] = nextTexture;
1552 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001553
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001554 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001555 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001556 nextTexture->getTexParams();
1557 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001558
twiz@google.com0f31ca72011-03-18 17:38:11 +00001559 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1560 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001561 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001562 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001563 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001564 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001565
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001566 if (newTexParams.fFilter != oldTexParams.fFilter) {
1567 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001568 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1569 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001570 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001571 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1572 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001573 newTexParams.fFilter));
1574 }
1575 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1576 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001577 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1578 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001579 newTexParams.fWrapS));
1580 }
1581 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1582 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001583 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1584 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001585 newTexParams.fWrapT));
1586 }
1587 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001588
1589 // The texture matrix has to compensate for texture width/height
1590 // and NPOT-embedded-in-POT
1591 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001592 } else {
1593 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001594 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001595 }
1596 }
1597 }
1598
1599 flushRenderTarget();
1600
1601 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1602 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1603 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001604 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001605 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001606 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001607 }
1608 }
1609
bsalomon@google.comd302f142011-03-03 13:54:13 +00001610 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1611 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001612 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001613 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001614 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001615 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001616 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001617 }
1618 GR_GL(ColorMask(mask, mask, mask, mask));
1619 }
1620
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001621 if (GR_GL_SUPPORT_DESKTOP) {
1622 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1623 // smooth lines.
1624 if (fDirtyFlags.fRenderTargetChanged ||
1625 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1626 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1627 GrGLint msaa = 0;
1628 // only perform query if we know MSAA is supported.
1629 // calling on non-MSAA target caused a crash in one environment,
1630 // though I don't think it should.
1631 if (fAASamples[kHigh_AALevel]) {
1632 GR_GL_GetIntegerv(GR_GL_SAMPLE_BUFFERS, &msaa);
1633 }
1634 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1635 if (msaa) {
1636 GR_GL(Enable(GR_GL_MULTISAMPLE));
1637 } else {
1638 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1639 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001640 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001641 if (msaa) {
1642 GR_GL(Disable(GR_GL_MULTISAMPLE));
1643 }
1644 GR_GL(Disable(GR_GL_LINE_SMOOTH));
reed@google.comac10a2d2010-12-22 21:39:39 +00001645 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001646 }
1647 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001648
1649 bool blendOff = canDisableBlend();
1650 if (fHWBlendDisabled != blendOff) {
1651 if (blendOff) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001652 GR_GL(Disable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001653 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001654 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001655 }
1656 fHWBlendDisabled = blendOff;
1657 }
1658
1659 if (!blendOff) {
1660 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1661 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1662 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1663 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1664 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1665 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1666 }
bsalomon@google.com080773c2011-03-15 19:09:25 +00001667 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1668 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1669 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1670
1671 float c[] = {
1672 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1673 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1674 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1675 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1676 };
1677 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1678 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1679 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001680 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001681
bsalomon@google.comd302f142011-03-03 13:54:13 +00001682 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1683 switch (fCurrDrawState.fDrawFace) {
1684 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001685 GR_GL(Enable(GR_GL_CULL_FACE));
1686 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001687 break;
1688 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001689 GR_GL(Enable(GR_GL_CULL_FACE));
1690 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001691 break;
1692 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001693 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001694 break;
1695 default:
1696 GrCrash("Unknown draw face.");
1697 }
1698 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1699 }
1700
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001701#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001702 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001703 for (int s = 0; s < kNumStages; ++s) {
1704 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1705 NULL == fCurrDrawState.fRenderTarget ||
1706 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001707 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001708 fCurrDrawState.fRenderTarget);
1709 }
1710#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001711
reed@google.comac10a2d2010-12-22 21:39:39 +00001712 flushStencil();
1713
bsalomon@google.comd302f142011-03-03 13:54:13 +00001714 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001715 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001716 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001717}
1718
1719void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001720 if (fHWGeometryState.fVertexBuffer != buffer) {
1721 fHWGeometryState.fArrayPtrsDirty = true;
1722 fHWGeometryState.fVertexBuffer = buffer;
1723 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001724}
1725
1726void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1727 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1728 buffer == fGeometrySrc.fVertexBuffer));
1729
1730 if (fHWGeometryState.fVertexBuffer == buffer) {
1731 // deleting bound buffer does implied bind to 0
1732 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001733 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001734 }
1735}
1736
1737void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1738 fGeometrySrc.fIndexBuffer = buffer;
1739}
1740
1741void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1742 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1743 buffer == fGeometrySrc.fIndexBuffer));
1744
1745 if (fHWGeometryState.fIndexBuffer == buffer) {
1746 // deleting bound buffer does implied bind to 0
1747 fHWGeometryState.fIndexBuffer = NULL;
1748 }
1749}
1750
reed@google.comac10a2d2010-12-22 21:39:39 +00001751void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1752 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001753 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001754 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001755 }
1756 if (fHWDrawState.fRenderTarget == renderTarget) {
1757 fHWDrawState.fRenderTarget = NULL;
1758 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001759}
1760
1761void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001762 for (int s = 0; s < kNumStages; ++s) {
1763 if (fCurrDrawState.fTextures[s] == texture) {
1764 fCurrDrawState.fTextures[s] = NULL;
1765 }
1766 if (fHWDrawState.fTextures[s] == texture) {
1767 // deleting bound texture does implied bind to 0
1768 fHWDrawState.fTextures[s] = NULL;
1769 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001770 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001771}
1772
reed@google.comac10a2d2010-12-22 21:39:39 +00001773bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001774 GrGLenum* internalFormat,
1775 GrGLenum* format,
1776 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001777 switch (config) {
1778 case GrTexture::kRGBA_8888_PixelConfig:
1779 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001780 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001781 if (GR_GL_SUPPORT_ES) {
1782 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1783 // format for a BGRA is BGRA not RGBA (as on desktop)
1784 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1785 } else {
1786 *internalFormat = GR_GL_RGBA;
1787 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001788 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001789 break;
1790 case GrTexture::kRGB_565_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001791 *format = GR_GL_RGB;
1792 *internalFormat = GR_GL_RGB;
1793 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001794 break;
1795 case GrTexture::kRGBA_4444_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001796 *format = GR_GL_RGBA;
1797 *internalFormat = GR_GL_RGBA;
1798 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001799 break;
1800 case GrTexture::kIndex_8_PixelConfig:
1801 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001802 *format = GR_GL_PALETTE8_RGBA8;
1803 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001804 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001805 } else {
1806 return false;
1807 }
1808 break;
1809 case GrTexture::kAlpha_8_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001810 *format = GR_GL_ALPHA;
1811 *internalFormat = GR_GL_ALPHA;
1812 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001813 break;
1814 default:
1815 return false;
1816 }
1817 return true;
1818}
1819
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001820void GrGpuGL::setTextureUnit(int unit) {
1821 GrAssert(unit >= 0 && unit < kNumStages);
1822 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001823 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001824 fActiveTextureUnitIdx = unit;
1825 }
1826}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001827
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001828void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001829 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1830 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001831 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1832 }
1833}
1834
reed@google.comac10a2d2010-12-22 21:39:39 +00001835/* On ES the internalFormat and format must match for TexImage and we use
1836 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1837 decide the internalFormat. However, on ES internalFormat for
1838 RenderBufferStorage* has to be a specific format (not a base format like
1839 GL_RGBA).
1840 */
twiz@google.com0f31ca72011-03-18 17:38:11 +00001841bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001842 switch (config) {
1843 case GrTexture::kRGBA_8888_PixelConfig:
1844 case GrTexture::kRGBX_8888_PixelConfig:
1845 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001846 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001847 return true;
1848 } else {
1849 return false;
1850 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001851 case GrTexture::kRGB_565_PixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001852 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1853 // with FBO extension desktop GL has
1854 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001855 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001856 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001857 case GrTexture::kRGBA_4444_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001858 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001859 return true;
1860 default:
1861 return false;
1862 }
1863}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001864
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001865void GrGpuGL::resetDirtyFlags() {
1866 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1867}
1868
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001869void GrGpuGL::setBuffers(bool indexed,
1870 int* extraVertexOffset,
1871 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001872
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001873 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001874
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001875 GrGLVertexBuffer* vbuf;
1876 switch (fGeometrySrc.fVertexSrc) {
1877 case kBuffer_GeometrySrcType:
1878 *extraVertexOffset = 0;
1879 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1880 break;
1881 case kArray_GeometrySrcType:
1882 case kReserved_GeometrySrcType:
1883 finalizeReservedVertices();
1884 *extraVertexOffset = fCurrPoolStartVertex;
1885 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1886 break;
1887 default:
1888 vbuf = NULL; // suppress warning
1889 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001890 }
1891
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001892 GrAssert(NULL != vbuf);
1893 GrAssert(!vbuf->isLocked());
1894 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001895 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001896 fHWGeometryState.fArrayPtrsDirty = true;
1897 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001898 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001899
1900 if (indexed) {
1901 GrAssert(NULL != extraIndexOffset);
1902
1903 GrGLIndexBuffer* ibuf;
1904 switch (fGeometrySrc.fIndexSrc) {
1905 case kBuffer_GeometrySrcType:
1906 *extraIndexOffset = 0;
1907 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1908 break;
1909 case kArray_GeometrySrcType:
1910 case kReserved_GeometrySrcType:
1911 finalizeReservedIndices();
1912 *extraIndexOffset = fCurrPoolStartIndex;
1913 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1914 break;
1915 default:
1916 ibuf = NULL; // suppress warning
1917 GrCrash("Unknown geometry src type!");
1918 }
1919
1920 GrAssert(NULL != ibuf);
1921 GrAssert(!ibuf->isLocked());
1922 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001923 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001924 fHWGeometryState.fIndexBuffer = ibuf;
1925 }
1926 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001927}