blob: 1d159e3dcc4c963dd93165c8aebc990b5fe51e7a [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
bsalomon@google.com1da07462011-03-10 14:51:57 +00002 Copyright 2011 Google Inc.
reed@google.comac10a2d2010-12-22 21:39:39 +00003
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#include "GrGpuGL.h"
18#include "GrMemory.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000019
twiz@google.com0f31ca72011-03-18 17:38:11 +000020static const GrGLuint GR_MAX_GLUINT = ~0;
21static const GrGLint GR_INVAL_GLINT = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000022
bsalomon@google.com316f99232011-01-13 21:28:12 +000023// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000024// mucking with the state of any of the stages.
bsalomon@google.com316f99232011-01-13 21:28:12 +000025static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000026
reed@google.comac10a2d2010-12-22 21:39:39 +000027#define SKIP_CACHE_CHECK true
28
twiz@google.com0f31ca72011-03-18 17:38:11 +000029static const GrGLenum gXfermodeCoeff2Blend[] = {
30 GR_GL_ZERO,
31 GR_GL_ONE,
32 GR_GL_SRC_COLOR,
33 GR_GL_ONE_MINUS_SRC_COLOR,
34 GR_GL_DST_COLOR,
35 GR_GL_ONE_MINUS_DST_COLOR,
36 GR_GL_SRC_ALPHA,
37 GR_GL_ONE_MINUS_SRC_ALPHA,
38 GR_GL_DST_ALPHA,
39 GR_GL_ONE_MINUS_DST_ALPHA,
40 GR_GL_CONSTANT_COLOR,
41 GR_GL_ONE_MINUS_CONSTANT_COLOR,
42 GR_GL_CONSTANT_ALPHA,
43 GR_GL_ONE_MINUS_CONSTANT_ALPHA,
reed@google.comac10a2d2010-12-22 21:39:39 +000044};
45
bsalomon@google.com080773c2011-03-15 19:09:25 +000046bool GrGpuGL::BlendCoefReferencesConstant(GrBlendCoeff coeff) {
47 static const bool gCoeffReferencesBlendConst[] = {
48 false,
49 false,
50 false,
51 false,
52 false,
53 false,
54 false,
55 false,
56 false,
57 false,
58 true,
59 true,
60 true,
61 true,
62 };
63 return gCoeffReferencesBlendConst[coeff];
64 GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
65}
66
67GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
68GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
69GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
70GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
71GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
72GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
73GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
74GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
75GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
76GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
77GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
78GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
79GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
80GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
81
82GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
83
reed@google.comac10a2d2010-12-22 21:39:39 +000084///////////////////////////////////////////////////////////////////////////////
85
bsalomon@google.comd302f142011-03-03 13:54:13 +000086void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
87 GrSamplerState::SampleMode mode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000088 GrMatrix* matrix) {
89 GrAssert(NULL != texture);
90 GrAssert(NULL != matrix);
91 if (GR_Scalar1 != texture->contentScaleX() ||
92 GR_Scalar1 != texture->contentScaleY()) {
93 if (GrSamplerState::kRadial_SampleMode == mode) {
94 GrMatrix scale;
95 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
96 matrix->postConcat(scale);
97 } else if (GrSamplerState::kNormal_SampleMode == mode) {
98 GrMatrix scale;
99 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
100 matrix->postConcat(scale);
101 } else {
102 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
103 }
104 }
105 GrGLTexture::Orientation orientation = texture->orientation();
106 if (GrGLTexture::kBottomUp_Orientation == orientation) {
107 GrMatrix invY;
108 invY.setAll(GR_Scalar1, 0, 0,
109 0, -GR_Scalar1, GR_Scalar1,
110 0, 0, GrMatrix::I()[8]);
111 matrix->postConcat(invY);
112 } else {
113 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
114 }
115}
116
bsalomon@google.comd302f142011-03-03 13:54:13 +0000117bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000118 const GrSamplerState& sampler) {
119 GrAssert(NULL != texture);
120 if (!sampler.getMatrix().isIdentity()) {
121 return false;
122 }
123 if (GR_Scalar1 != texture->contentScaleX() ||
124 GR_Scalar1 != texture->contentScaleY()) {
125 return false;
126 }
127 GrGLTexture::Orientation orientation = texture->orientation();
128 if (GrGLTexture::kBottomUp_Orientation == orientation) {
129 return false;
130 } else {
131 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
132 }
133 return true;
134}
135
136///////////////////////////////////////////////////////////////////////////////
137
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000138static bool gPrintStartupSpew;
139
twiz@google.com59a190b2011-03-14 21:23:01 +0000140static bool fbo_test(int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000141
twiz@google.com0f31ca72011-03-18 17:38:11 +0000142 GrGLint savedFBO;
143 GrGLint savedTexUnit;
144 GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000145 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000146
twiz@google.com0f31ca72011-03-18 17:38:11 +0000147 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000148
twiz@google.com0f31ca72011-03-18 17:38:11 +0000149 GrGLuint testFBO;
twiz@google.com59a190b2011-03-14 21:23:01 +0000150 GR_GL(GenFramebuffers(1, &testFBO));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000151 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000152 GrGLuint testRTTex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 GR_GL(GenTextures(1, &testRTTex));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000154 GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000155 // some implementations require texture to be mip-map complete before
156 // FBO with level 0 bound as color attachment will be framebuffer complete.
twiz@google.com0f31ca72011-03-18 17:38:11 +0000157 GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
158 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
159 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
160 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000161 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000162 GR_GL_TEXTURE_2D, testRTTex, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000163 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000164 GR_GL(DeleteFramebuffers(1, &testFBO));
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000166
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000167 GR_GL(ActiveTexture(savedTexUnit));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000168 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000169
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000170 return status == GR_GL_FRAMEBUFFER_COMPLETE;
reed@google.comac10a2d2010-12-22 21:39:39 +0000171}
172
reed@google.comac10a2d2010-12-22 21:39:39 +0000173GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000174
reed@google.comeeeb5a02010-12-23 15:12:59 +0000175 if (gPrintStartupSpew) {
176 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
177 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000178 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000179 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000180 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000181 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000182 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000183 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000184 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000185 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000186 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000187
188 GrGLClearErr();
189
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000190 resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000191
twiz@google.com0f31ca72011-03-18 17:38:11 +0000192 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000193 // check FS and fixed-function texture unit limits
194 // we only use textures in the fragment stage currently.
195 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000196 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
197 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
198 GrAssert(maxTextureUnits > kNumStages);
199 }
200 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
201 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
202 GrAssert(maxTextureUnits > kNumStages);
203 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000204
reed@google.comac10a2d2010-12-22 21:39:39 +0000205 ////////////////////////////////////////////////////////////////////////////
206 // Check for supported features.
207
208 int major, minor;
209 gl_version(&major, &minor);
210
twiz@google.com0f31ca72011-03-18 17:38:11 +0000211 GrGLint numFormats;
212 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
213 GrAutoSTMalloc<10, GrGLint> formats(numFormats);
214 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000216 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000217 f8bitPaletteSupport = true;
218 break;
219 }
220 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000221
222 if (gPrintStartupSpew) {
223 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
224 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000225
226 GR_STATIC_ASSERT(0 == kNone_AALevel);
227 GR_STATIC_ASSERT(1 == kLow_AALevel);
228 GR_STATIC_ASSERT(2 == kMed_AALevel);
229 GR_STATIC_ASSERT(3 == kHigh_AALevel);
230
231 memset(fAASamples, 0, sizeof(fAASamples));
232 fMSFBOType = kNone_MSFBO;
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000233 if (GR_GL_SUPPORT_ES) {
234 if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000235 // chrome's extension is equivalent to the EXT msaa
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000236 // and fbo_blit extensions.
237 fMSFBOType = kDesktopEXT_MSFBO;
238 } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
239 fMSFBOType = kAppleES_MSFBO;
240 }
241 } else {
242 GrAssert(GR_GL_SUPPORT_DESKTOP);
243 if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
244 fMSFBOType = kDesktopARB_MSFBO;
245 } else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
246 has_gl_extension("GL_EXT_framebuffer_blit")) {
247 fMSFBOType = kDesktopEXT_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000248 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000249 }
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000250 if (gPrintStartupSpew) {
251 switch (fMSFBOType) {
252 case kNone_MSFBO:
253 GrPrintf("MSAA Support: NONE\n");
254 break;
255 case kDesktopARB_MSFBO:
256 GrPrintf("MSAA Support: DESKTOP ARB.\n");
257 break;
258 case kDesktopEXT_MSFBO:
259 GrPrintf("MSAA Support: DESKTOP EXT.\n");
260 break;
261 case kAppleES_MSFBO:
262 GrPrintf("MSAA Support: APPLE ES.\n");
263 break;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000264 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000265 }
266
267 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000268 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000269 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000270 if (maxSamples > 1 ) {
271 fAASamples[kNone_AALevel] = 0;
272 fAASamples[kLow_AALevel] = GrMax(2,
273 GrFixedFloorToInt((GR_FixedHalf) *
274 maxSamples));
275 fAASamples[kMed_AALevel] = GrMax(2,
276 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
277 maxSamples));
278 fAASamples[kHigh_AALevel] = maxSamples;
279 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000280 if (gPrintStartupSpew) {
281 GrPrintf("\tMax Samples: %d\n", maxSamples);
282 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000283 }
284
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000285 if (GR_GL_SUPPORT_DESKTOP) {
286 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
287 has_gl_extension("GL_EXT_stencil_wrap");
288 } else {
289 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
290 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000291 if (gPrintStartupSpew) {
292 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
293 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000294
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000295 if (GR_GL_SUPPORT_DESKTOP) {
296 // we could also look for GL_ATI_separate_stencil extension or
297 // GL_EXT_stencil_two_side but they use different function signatures
298 // than GL2.0+ (and than each other).
299 fTwoSidedStencilSupport = (major >= 2);
300 // supported on GL 1.4 and higher or by extension
301 fStencilWrapOpsSupport = (major > 1) ||
302 ((1 == major) && (minor >= 4)) ||
303 has_gl_extension("GL_EXT_stencil_wrap");
304 } else {
305 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
306 // an ES1 extension.
307 fTwoSidedStencilSupport = (major >= 2);
308 // stencil wrap support is in ES2, ES1 requires extension.
309 fStencilWrapOpsSupport = (major > 1) ||
310 has_gl_extension("GL_OES_stencil_wrap");
311 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000312 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000313 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
314 (fTwoSidedStencilSupport ? "YES" : "NO"),
315 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000316 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000317
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000318 if (GR_GL_SUPPORT_DESKTOP) {
319 fRGBA8Renderbuffer = true;
320 } else {
321 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
322 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000323 if (gPrintStartupSpew) {
324 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
325 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000326
327
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000328 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000329 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000330 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
331 }
332 }
333
334 if (GR_GL_SUPPORT_DESKTOP) {
335 fBufferLockSupport = true; // we require VBO support and the desktop VBO
336 // extension includes glMapBuffer.
337 } else {
338 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
339 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000340
reed@google.comeeeb5a02010-12-23 15:12:59 +0000341 if (gPrintStartupSpew) {
342 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
343 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000344
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000345 if (GR_GL_SUPPORT_DESKTOP) {
346 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
347 fNPOTTextureTileSupport = true;
348 fNPOTTextureSupport = true;
349 } else {
350 fNPOTTextureTileSupport = false;
351 fNPOTTextureSupport = false;
352 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000353 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000354 if (major >= 2) {
355 fNPOTTextureSupport = true;
356 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
357 } else {
358 fNPOTTextureSupport =
359 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
360 fNPOTTextureTileSupport = false;
361 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000362 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000363
reed@google.comac10a2d2010-12-22 21:39:39 +0000364 ////////////////////////////////////////////////////////////////////////////
365 // Experiments to determine limitations that can't be queried. TODO: Make
366 // these a preprocess that generate some compile time constants.
367
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000368 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000369
twiz@google.com59a190b2011-03-14 21:23:01 +0000370 bool simpleFBOSuccess = fbo_test(128, 128);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000371 if (gPrintStartupSpew) {
372 if (!simpleFBOSuccess) {
373 GrPrintf("FBO Sanity Test: FAILED\n");
374 } else {
375 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000376 }
377 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000378 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000379
reed@google.comac10a2d2010-12-22 21:39:39 +0000380 /* Experimentation has found that some GLs that support NPOT textures
381 do not support FBOs with a NPOT texture. They report "unsupported" FBO
382 status. I don't know how to explicitly query for this. Do an
383 experiment. Note they may support NPOT with a renderbuffer but not a
384 texture. Presumably, the implementation bloats the renderbuffer
385 internally to the next POT.
386 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000387 bool fNPOTRenderTargetSupport = false;
388 if (fNPOTTextureSupport) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000389 fNPOTRenderTargetSupport = fbo_test(200, 200);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000390 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000391
bsalomon@google.com0748f212011-02-01 22:56:16 +0000392 if (gPrintStartupSpew) {
393 if (fNPOTTextureSupport) {
394 GrPrintf("NPOT textures supported\n");
395 if (fNPOTTextureTileSupport) {
396 GrPrintf("NPOT texture tiling supported\n");
397 } else {
398 GrPrintf("NPOT texture tiling NOT supported\n");
399 }
400 if (fNPOTRenderTargetSupport) {
401 GrPrintf("NPOT render targets supported\n");
402 } else {
403 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000404 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000405 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000406 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000407 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000408 }
409
reed@google.comac10a2d2010-12-22 21:39:39 +0000410 /* The iPhone 4 has a restriction that for an FBO with texture color
411 attachment with height <= 8 then the width must be <= height. Here
412 we look for such a limitation.
413 */
414 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000415 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000416 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
reed@google.comac10a2d2010-12-22 21:39:39 +0000417
reed@google.comeeeb5a02010-12-23 15:12:59 +0000418 if (gPrintStartupSpew) {
419 GrPrintf("Small height FBO texture experiments\n");
420 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000421
twiz@google.com0f31ca72011-03-18 17:38:11 +0000422 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
423 GrGLuint w = maxRenderSize;
424 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000425 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000426 if (gPrintStartupSpew) {
427 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
428 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000429 fMinRenderTargetHeight = i;
430 break;
431 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000432 if (gPrintStartupSpew) {
433 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
434 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000435 }
436 }
437 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
438
reed@google.comeeeb5a02010-12-23 15:12:59 +0000439 if (gPrintStartupSpew) {
440 GrPrintf("Small width FBO texture experiments\n");
441 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000442 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000443 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
444 GrGLuint w = i;
445 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000446 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000447 if (gPrintStartupSpew) {
448 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
449 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000450 fMinRenderTargetWidth = i;
451 break;
452 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000453 if (gPrintStartupSpew) {
454 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
455 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000456 }
457 }
458 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
459
twiz@google.com0f31ca72011-03-18 17:38:11 +0000460 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000461}
462
463GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000464}
465
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000466void GrGpuGL::resetContext() {
467 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000468 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000469 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000470
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000471 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000472 GR_GL(Disable(GR_GL_DEPTH_TEST));
473 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000474
twiz@google.com0f31ca72011-03-18 17:38:11 +0000475 GR_GL(Disable(GR_GL_CULL_FACE));
476 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000477 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000478
twiz@google.com0f31ca72011-03-18 17:38:11 +0000479 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000480 if (GR_GL_SUPPORT_DESKTOP) {
481 GR_GL(Disable(GR_GL_LINE_SMOOTH));
482 GR_GL(Disable(GR_GL_POINT_SMOOTH));
483 GR_GL(Disable(GR_GL_MULTISAMPLE));
484 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000485
twiz@google.com0f31ca72011-03-18 17:38:11 +0000486 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000487 fHWDrawState.fFlagBits = 0;
488
reed@google.comac10a2d2010-12-22 21:39:39 +0000489 // we only ever use lines in hairline mode
490 GR_GL(LineWidth(1));
491
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000492 // invalid
493 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000494
reed@google.comac10a2d2010-12-22 21:39:39 +0000495 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000496 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
497 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000498
499 fHWDrawState.fBlendConstant = 0x00000000;
500 GR_GL(BlendColor(0,0,0,0));
501
reed@google.comac10a2d2010-12-22 21:39:39 +0000502 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000503
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000504 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000505
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000506 for (int s = 0; s < kNumStages; ++s) {
507 fHWDrawState.fTextures[s] = NULL;
508 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
509 -GR_ScalarMax,
510 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000511
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000512 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000513 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000514
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000515 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000516 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000517 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000518 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000519
bsalomon@google.comd302f142011-03-03 13:54:13 +0000520 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000521 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000522 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000523
524 fHWGeometryState.fIndexBuffer = NULL;
525 fHWGeometryState.fVertexBuffer = NULL;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000526 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0));
527 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000528 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000529
twiz@google.com0f31ca72011-03-18 17:38:11 +0000530 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000531 fHWDrawState.fRenderTarget = NULL;
532}
533
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000534GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
reed@google.comac10a2d2010-12-22 21:39:39 +0000535 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000536 int stencilBits,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000537 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000538 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000539 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
540 rtIDs.fStencilRenderbufferID = 0;
541 rtIDs.fMSColorRenderbufferID = 0;
542 rtIDs.fTexFBOID = 0;
543 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000544 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000545
546 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000547 viewport.fLeft = 0;
548 viewport.fBottom = 0;
549 viewport.fWidth = width;
550 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000551
twiz@google.com0f31ca72011-03-18 17:38:11 +0000552 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
553 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000554
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000555 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000556}
557
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000558GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000559
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000560 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000561
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000562 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000563 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
564 rtIDs.fMSColorRenderbufferID = 0;
565 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000566
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000567 GrGLIRect viewport;
568 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000569 GrGLuint stencilBits;
570 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000571
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000572 rtIDs.fOwnIDs = false;
573
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000574 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000575}
576
bsalomon@google.com5782d712011-01-21 21:03:59 +0000577///////////////////////////////////////////////////////////////////////////////
578
twiz@google.com0f31ca72011-03-18 17:38:11 +0000579static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000580
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000581struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000582 GrGLenum fEnum;
583 GrGLuint fBits;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000584};
585
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000586const StencilFormat* GrGLStencilFormats() {
587 // defines stencil formats from more to less preferred
588 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000589 {GR_GL_STENCIL_INDEX8, 8},
590 {GR_GL_STENCIL_INDEX16, 16},
591 {GR_GL_DEPTH24_STENCIL8, 8},
592 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000593 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS},
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000594 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000595 {0, 0}
596 };
597
598 static const StencilFormat esStencilFormats[] = {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000599 {GR_GL_STENCIL_INDEX8, 8},
600 {GR_GL_DEPTH24_STENCIL8, 8},
601 {GR_GL_STENCIL_INDEX4, 4},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000602 {0, 0}
603 };
604
605 if (GR_GL_SUPPORT_DESKTOP) {
606 return desktopStencilFormats;
607 } else {
608 return esStencilFormats;
609 }
610}
611
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000612// good to set a break-point here to know when createTexture fails
613static GrTexture* return_null_texture() {
614// GrAssert(!"null texture");
615 return NULL;
616}
617
618#if GR_DEBUG
619static size_t as_size_t(int x) {
620 return x;
621}
622#endif
623
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000624GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc,
625 const void* srcData,
626 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000627
628#if GR_COLLECT_STATS
629 ++fStats.fTextureCreateCnt;
630#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000631
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000632 setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000633
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000634 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000635 GR_GL_NEAREST,
636 GR_GL_CLAMP_TO_EDGE,
637 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000638 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000639
reed@google.comac10a2d2010-12-22 21:39:39 +0000640 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000641 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000642
643 glDesc.fContentWidth = desc.fWidth;
644 glDesc.fContentHeight = desc.fHeight;
645 glDesc.fAllocWidth = desc.fWidth;
646 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000647 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000648 glDesc.fFormat = desc.fFormat;
649
650 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag);
651 if (!canBeTexture(desc.fFormat,
652 &internalFormat,
653 &glDesc.fUploadFormat,
654 &glDesc.fUploadType)) {
655 return return_null_texture();
656 }
657
658 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000659 GrGLint samples = fAASamples[desc.fAALevel];
reed@google.comac10a2d2010-12-22 21:39:39 +0000660 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) {
661 GrPrintf("AA RT requested but not supported on this platform.");
662 }
663
664 GR_GL(GenTextures(1, &glDesc.fTextureID));
665 if (!glDesc.fTextureID) {
666 return return_null_texture();
667 }
668
669 glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat);
670
reed@google.com5e762232011-04-04 18:15:49 +0000671 // in case we need a temporary, trimmed copy of the src pixels
672 GrAutoSMalloc<128 * 128> trimStorage;
673
reed@google.comac10a2d2010-12-22 21:39:39 +0000674 /*
675 * check if our srcData has extra bytes past each row. If so, we need
676 * to trim those off here, since GL doesn't let us pass the rowBytes as
677 * a parameter to glTexImage2D
678 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000679 if (GR_GL_SUPPORT_DESKTOP) {
680 if (srcData) {
681 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
682 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000683 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000684 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000685 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
686 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000687 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000688 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000689 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000690 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000691 for (uint32_t y = 0; y < desc.fHeight; y++) {
692 memcpy(dst, src, trimRowBytes);
693 src += rowBytes;
694 dst += trimRowBytes;
695 }
696 // now point srcData to our trimmed version
697 srcData = trimStorage.get();
698 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000699 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000700
reed@google.comac10a2d2010-12-22 21:39:39 +0000701 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000702 if (!this->npotRenderTargetSupport()) {
703 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
704 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
705 }
706
reed@google.comac10a2d2010-12-22 21:39:39 +0000707 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
708 glDesc.fAllocWidth);
709 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
710 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000711 } else if (!this->npotTextureSupport()) {
712 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
713 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000714 }
715
twiz@google.com0f31ca72011-03-18 17:38:11 +0000716 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
717 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
718 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000719 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000720 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
721 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000722 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000723 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
724 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000725 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000726 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
727 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000728 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000729
twiz@google.com0f31ca72011-03-18 17:38:11 +0000730 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000731 if (GrTexture::kIndex_8_PixelConfig == desc.fFormat &&
732 supports8BitPalette()) {
733 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
734 GrAssert(desc.fWidth == glDesc.fAllocWidth);
735 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000736 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
737 kColorTableSize;
738 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000739 glDesc.fAllocWidth, glDesc.fAllocHeight,
740 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000741 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000742 } else {
743 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
744 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000745 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000746 glDesc.fAllocWidth, glDesc.fAllocHeight,
747 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000748 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000749 desc.fHeight, glDesc.fUploadFormat,
750 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000751 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000752
753 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
754 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
755 uint32_t maxTexels = extraW * extraH;
756 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
757 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
758
759 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
760
761 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
762 if (extraH) {
763 uint8_t* lastRowStart = (uint8_t*) srcData +
764 (desc.fHeight - 1) * rowSize;
765 uint8_t* extraRowStart = (uint8_t*)texels.get();
766
767 for (uint32_t i = 0; i < extraH; ++i) {
768 memcpy(extraRowStart, lastRowStart, rowSize);
769 extraRowStart += rowSize;
770 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000771 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000772 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
773 texels.get()));
774 }
775 if (extraW) {
776 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
777 uint8_t* extraTexel = (uint8_t*)texels.get();
778 for (uint32_t j = 0; j < desc.fHeight; ++j) {
779 for (uint32_t i = 0; i < extraW; ++i) {
780 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
781 extraTexel += glDesc.fUploadByteCount;
782 }
783 edgeTexel += rowSize;
784 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000785 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000786 desc.fHeight, glDesc.fUploadFormat,
787 glDesc.fUploadType, texels.get()));
788 }
789 if (extraW && extraH) {
790 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
791 - glDesc.fUploadByteCount;
792 uint8_t* extraTexel = (uint8_t*)texels.get();
793 for (uint32_t i = 0; i < extraW*extraH; ++i) {
794 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
795 extraTexel += glDesc.fUploadByteCount;
796 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000797 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000798 extraW, extraH, glDesc.fUploadFormat,
799 glDesc.fUploadType, texels.get()));
800 }
801
802 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000803 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000804 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
805 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000806 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000807 }
808 }
809
810 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
811
812 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
813 rtIDs.fStencilRenderbufferID = 0;
814 rtIDs.fMSColorRenderbufferID = 0;
815 rtIDs.fRTFBOID = 0;
816 rtIDs.fTexFBOID = 0;
817 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000818 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000819
820 if (renderTarget) {
821#if GR_COLLECT_STATS
822 ++fStats.fRenderTargetCreateCnt;
823#endif
824 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000825 GrGLenum status;
826 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000827
828 // If need have both RT flag and srcData we have
829 // to invert the data before uploading because FBO
830 // will be rendered bottom up
831 GrAssert(NULL == srcData);
832 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
833
twiz@google.com59a190b2011-03-14 21:23:01 +0000834 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000835 GrAssert(rtIDs.fTexFBOID);
836
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000837 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000838 // to one and then resolve to the texture bound to the other.
839 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000840 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000841 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000842 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000843 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
844 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000845 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000846 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000847 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
848 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000849 return return_null_texture();
850 }
851 } else {
852 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
853 }
bsalomon@google.comf6a7c112011-03-24 16:14:10 +0000854 if (!(kNoStencil_TextureFlag & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000855 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000856 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000857 }
858
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000859 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000860 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000861 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000862 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000863
twiz@google.com0f31ca72011-03-18 17:38:11 +0000864 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000865
866 const StencilFormat* stencilFormats = GrGLStencilFormats();
867 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000868 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000869 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000870 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000871 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000872 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000873 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000874 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000875 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000876 glDesc.fAllocWidth,
877 glDesc.fAllocHeight));
878 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000879 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000880 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000881 glDesc.fAllocWidth,
882 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000883 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000884 err = GrGLGetGLInterface()->fGetError();
885 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000886 continue;
887 }
888 }
889 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
890 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000891 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000892 rtIDs.fMSColorRenderbufferID));
893 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000894 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000895 samples,
896 msColorRenderbufferFormat,
897 glDesc.fAllocWidth,
898 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000899 err = GrGLGetGLInterface()->fGetError();
900 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000901 continue;
902 }
903 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000904 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000905
906#if GR_COLLECT_STATS
907 ++fStats.fRenderTargetChngCnt;
908#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000909 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
910 GR_GL_COLOR_ATTACHMENT0,
911 GR_GL_TEXTURE_2D,
912 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000913 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000914 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
915 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000916 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
917 status, desc.fWidth, desc.fHeight);
918 continue;
919 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000920 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000921 #if GR_COLLECT_STATS
922 ++fStats.fRenderTargetChngCnt;
923 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000924 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
925 GR_GL_COLOR_ATTACHMENT0,
926 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000927 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000928
929 }
930 if (rtIDs.fStencilRenderbufferID) {
931 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000932 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
933 GR_GL_STENCIL_ATTACHMENT,
934 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000935 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000936 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000937 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000938
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000939 if (GR_GL_SUPPORT_DESKTOP) {
940 // On some implementations you have to be bound as DEPTH_STENCIL.
941 // (Even binding to DEPTH and STENCIL separately with the same
942 // buffer doesn't work.)
943 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000944 status != GR_GL_FRAMEBUFFER_COMPLETE) {
945 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
946 GR_GL_STENCIL_ATTACHMENT,
947 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000948 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000949 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
950 GR_GL_DEPTH_STENCIL_ATTACHMENT,
951 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000952 rtIDs.fStencilRenderbufferID));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000953 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +0000954 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000955 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000956 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000957 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
958 status, desc.fWidth, desc.fHeight);
959 if (GR_GL_SUPPORT_DESKTOP) {
960 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000961 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
962 GR_GL_DEPTH_STENCIL_ATTACHMENT,
963 GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000964 0));
965 }
966 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000967 continue;
968 }
969 // we're successful!
970 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000971 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000972 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000973 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000974 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000975 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000976 }
977 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000978 break;
979 }
980 if (failed) {
981 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000982 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000983 }
984 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000985 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000986 }
987 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000988 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000989 }
990 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000991 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000992 }
993 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
994 return return_null_texture();
995 }
996 }
997#ifdef TRACE_TEXTURE_CREATION
998 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
999 tex->fTextureID, width, height, tex->fUploadByteCount);
1000#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001001 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001002
1003 if (0 != rtIDs.fTexFBOID) {
1004 GrRenderTarget* rt = tex->asRenderTarget();
1005 // We've messed with FBO state but may not have set the correct viewport
1006 // so just dirty the rendertarget state to force a resend.
1007 fHWDrawState.fRenderTarget = NULL;
1008
1009 // clear the new stencil buffer if we have one
bsalomon@google.comf6a7c112011-03-24 16:14:10 +00001010 if (!(desc.fFlags & kNoStencil_TextureFlag)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001011 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1012 fCurrDrawState.fRenderTarget = rt;
1013 eraseStencil(0, ~0);
1014 fCurrDrawState.fRenderTarget = rtSave;
1015 }
1016 }
1017 return tex;
1018}
1019
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001020GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001021 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001022 GR_GL(GenBuffers(1, &id));
1023 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001024 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001025 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001026 GrGLClearErr();
1027 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001028 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1029 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1030 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001031 GR_GL(DeleteBuffers(1, &id));
1032 // deleting bound buffer does implicit bind to 0
1033 fHWGeometryState.fVertexBuffer = NULL;
1034 return NULL;
1035 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001036 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001037 size, dynamic);
1038 fHWGeometryState.fVertexBuffer = vertexBuffer;
1039 return vertexBuffer;
1040 }
1041 return NULL;
1042}
1043
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001044GrIndexBuffer* GrGpuGL::createIndexBufferHelper(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001045 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001046 GR_GL(GenBuffers(1, &id));
1047 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001048 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001049 GrGLClearErr();
1050 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001051 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1052 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1053 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001054 GR_GL(DeleteBuffers(1, &id));
1055 // deleting bound buffer does implicit bind to 0
1056 fHWGeometryState.fIndexBuffer = NULL;
1057 return NULL;
1058 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001059 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001060 size, dynamic);
1061 fHWGeometryState.fIndexBuffer = indexBuffer;
1062 return indexBuffer;
1063 }
1064 return NULL;
1065}
1066
reed@google.comac10a2d2010-12-22 21:39:39 +00001067void GrGpuGL::flushScissor(const GrIRect* rect) {
1068 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001069 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001070 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001071
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001072 GrGLIRect scissor;
1073 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001074 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001075 rect->width(), rect->height());
1076 if (scissor.contains(vp)) {
1077 rect = NULL;
1078 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001079 }
1080
1081 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001082 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001083 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001084 fHWBounds.fScissorRect = scissor;
1085 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001086 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001087 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 fHWBounds.fScissorEnabled = true;
1089 }
1090 } else {
1091 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001092 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001093 fHWBounds.fScissorEnabled = false;
1094 }
1095 }
1096}
1097
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001098void GrGpuGL::eraseColorHelper(GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001099 if (NULL == fCurrDrawState.fRenderTarget) {
1100 return;
1101 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001102 flushRenderTarget();
1103 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001104 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001105 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001106 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001107 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001108 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001109 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1110 GrColorUnpackG(color)/255.f,
1111 GrColorUnpackB(color)/255.f,
1112 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001113 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001114}
1115
1116void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001117 if (NULL == fCurrDrawState.fRenderTarget) {
1118 return;
1119 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001120 flushRenderTarget();
1121 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001122 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001123 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001124 }
1125 GR_GL(StencilMask(mask));
1126 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001127 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001128 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001129}
1130
bsalomon@google.comd302f142011-03-03 13:54:13 +00001131void GrGpuGL::eraseStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001132 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001133#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001134 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001135 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001136 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001137#else
1138 // we could just clear the clip bit but when we go through
1139 // angle a partial stencil mask will cause clears to be
1140 // turned into draws. Our contract on GrDrawTarget says that
1141 // changing the clip between stencil passes may or may not
1142 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001143 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001144#endif
bsalomon@google.comd302f142011-03-03 13:54:13 +00001145 flushRenderTarget();
1146 flushScissor(&rect);
1147 GR_GL(StencilMask(clipStencilMask));
1148 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001149 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001150 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001151}
1152
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001153void GrGpuGL::forceRenderTargetFlushHelper() {
reed@google.comac10a2d2010-12-22 21:39:39 +00001154 flushRenderTarget();
1155}
1156
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001157bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height,
1158 GrTexture::PixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001159 GrGLenum internalFormat; // we don't use this for glReadPixels
1160 GrGLenum format;
1161 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001162 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1163 return false;
1164 }
1165
bsalomon@google.com18908aa2011-02-07 14:51:55 +00001166 if (NULL == fCurrDrawState.fRenderTarget) {
1167 return false;
1168 }
1169 flushRenderTarget();
1170
bsalomon@google.comd302f142011-03-03 13:54:13 +00001171 const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
1172
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001173 // the read rect is viewport-relative
1174 GrGLIRect readRect;
1175 readRect.setRelativeTo(glvp, left, top, width, height);
1176 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001177 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001178 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001179
1180 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1181 // API presents top-to-bottom
1182 {
1183 size_t stride = width * GrTexture::BytesPerPixel(config);
1184 GrAutoMalloc rowStorage(stride);
1185 void* tmp = rowStorage.get();
1186
1187 const int halfY = height >> 1;
1188 char* top = reinterpret_cast<char*>(buffer);
1189 char* bottom = top + (height - 1) * stride;
1190 for (int y = 0; y < halfY; y++) {
1191 memcpy(tmp, top, stride);
1192 memcpy(top, bottom, stride);
1193 memcpy(bottom, tmp, stride);
1194 top += stride;
1195 bottom -= stride;
1196 }
1197 }
1198 return true;
1199}
1200
1201void GrGpuGL::flushRenderTarget() {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001202
1203 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1204
reed@google.comac10a2d2010-12-22 21:39:39 +00001205 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
1206 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001207 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001208 #if GR_COLLECT_STATS
1209 ++fStats.fRenderTargetChngCnt;
1210 #endif
1211 rt->setDirty(true);
1212 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001213 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1214 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001215 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1216 }
1217 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001218 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001219 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001220 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001221 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001222 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001223 fHWBounds.fViewportRect = vp;
1224 }
1225 }
1226}
1227
twiz@google.com0f31ca72011-03-18 17:38:11 +00001228GrGLenum gPrimitiveType2GLMode[] = {
1229 GR_GL_TRIANGLES,
1230 GR_GL_TRIANGLE_STRIP,
1231 GR_GL_TRIANGLE_FAN,
1232 GR_GL_POINTS,
1233 GR_GL_LINES,
1234 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001235};
1236
bsalomon@google.comd302f142011-03-03 13:54:13 +00001237#define SWAP_PER_DRAW 0
1238
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001239#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001240 #if GR_MAC_BUILD
1241 #include <AGL/agl.h>
1242 #elif GR_WIN32_BUILD
1243 void SwapBuf() {
1244 DWORD procID = GetCurrentProcessId();
1245 HWND hwnd = GetTopWindow(GetDesktopWindow());
1246 while(hwnd) {
1247 DWORD wndProcID = 0;
1248 GetWindowThreadProcessId(hwnd, &wndProcID);
1249 if(wndProcID == procID) {
1250 SwapBuffers(GetDC(hwnd));
1251 }
1252 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1253 }
1254 }
1255 #endif
1256#endif
1257
bsalomon@google.comffca4002011-02-22 20:34:01 +00001258void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001259 uint32_t startVertex,
1260 uint32_t startIndex,
1261 uint32_t vertexCount,
1262 uint32_t indexCount) {
1263 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1264
twiz@google.com0f31ca72011-03-18 17:38:11 +00001265 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001266
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001267 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1268 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1269
1270 // our setupGeometry better have adjusted this to zero since
1271 // DrawElements always draws from the begining of the arrays for idx 0.
1272 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001273
1274 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001275 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001276#if SWAP_PER_DRAW
1277 glFlush();
1278 #if GR_MAC_BUILD
1279 aglSwapBuffers(aglGetCurrentContext());
1280 int set_a_break_pt_here = 9;
1281 aglSwapBuffers(aglGetCurrentContext());
1282 #elif GR_WIN32_BUILD
1283 SwapBuf();
1284 int set_a_break_pt_here = 9;
1285 SwapBuf();
1286 #endif
1287#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001288}
1289
bsalomon@google.comffca4002011-02-22 20:34:01 +00001290void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
reed@google.comac10a2d2010-12-22 21:39:39 +00001291 uint32_t startVertex,
1292 uint32_t vertexCount) {
1293 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1294
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001295 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1296
1297 // our setupGeometry better have adjusted this to zero.
1298 // DrawElements doesn't take an offset so we always adjus the startVertex.
1299 GrAssert(0 == startVertex);
1300
1301 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1302 // account for startVertex in the DrawElements case. So we always
1303 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001304 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001305#if SWAP_PER_DRAW
1306 glFlush();
1307 #if GR_MAC_BUILD
1308 aglSwapBuffers(aglGetCurrentContext());
1309 int set_a_break_pt_here = 9;
1310 aglSwapBuffers(aglGetCurrentContext());
1311 #elif GR_WIN32_BUILD
1312 SwapBuf();
1313 int set_a_break_pt_here = 9;
1314 SwapBuf();
1315 #endif
1316#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001317}
1318
reed@google.comac10a2d2010-12-22 21:39:39 +00001319void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) {
1320 GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget();
1321
1322 if (NULL != rt && rt->needsResolve()) {
1323 GrAssert(kNone_MSFBO != fMSFBOType);
1324 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001325 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001326 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001327 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001328 rt->textureFBOID()));
1329 #if GR_COLLECT_STATS
1330 ++fStats.fRenderTargetChngCnt;
1331 #endif
1332 // make sure we go through set render target
1333 fHWDrawState.fRenderTarget = NULL;
1334
twiz@google.com0f31ca72011-03-18 17:38:11 +00001335 GrGLint left = 0;
1336 GrGLint right = texture->width();
reed@google.comac10a2d2010-12-22 21:39:39 +00001337 // we will have rendered to the top of the FBO.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001338 GrGLint top = texture->allocHeight();
1339 GrGLint bottom = texture->allocHeight() - texture->height();
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001340 if (kAppleES_MSFBO == fMSFBOType) {
1341 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001342 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001343 GR_GL(Scissor(left, bottom, right-left, top-bottom));
twiz@google.com59a190b2011-03-14 21:23:01 +00001344 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001345 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001346 fHWBounds.fScissorEnabled = true;
1347 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001348 if (kDesktopARB_MSFBO != fMSFBOType) {
1349 // these respect the scissor during the blit, so disable it.
1350 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1351 flushScissor(NULL);
1352 }
twiz@google.com59a190b2011-03-14 21:23:01 +00001353 GR_GL(BlitFramebuffer(left, bottom, right, top,
reed@google.comac10a2d2010-12-22 21:39:39 +00001354 left, bottom, right, top,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001355 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001356 }
1357 rt->setDirty(false);
reed@google.comac10a2d2010-12-22 21:39:39 +00001358 }
1359}
1360
twiz@google.com0f31ca72011-03-18 17:38:11 +00001361static const GrGLenum grToGLStencilFunc[] = {
1362 GR_GL_ALWAYS, // kAlways_StencilFunc
1363 GR_GL_NEVER, // kNever_StencilFunc
1364 GR_GL_GREATER, // kGreater_StencilFunc
1365 GR_GL_GEQUAL, // kGEqual_StencilFunc
1366 GR_GL_LESS, // kLess_StencilFunc
1367 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1368 GR_GL_EQUAL, // kEqual_StencilFunc,
1369 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001370};
1371GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1372GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1373GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1374GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1375GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1376GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1377GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1378GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1379GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1380
twiz@google.com0f31ca72011-03-18 17:38:11 +00001381static const GrGLenum grToGLStencilOp[] = {
1382 GR_GL_KEEP, // kKeep_StencilOp
1383 GR_GL_REPLACE, // kReplace_StencilOp
1384 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1385 GR_GL_INCR, // kIncClamp_StencilOp
1386 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1387 GR_GL_DECR, // kDecClamp_StencilOp
1388 GR_GL_ZERO, // kZero_StencilOp
1389 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001390};
1391GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1392GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1393GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1394GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1395GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1396GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1397GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1398GR_STATIC_ASSERT(6 == kZero_StencilOp);
1399GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1400
reed@google.comac10a2d2010-12-22 21:39:39 +00001401void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001402 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001403
1404 // use stencil for clipping if clipping is enabled and the clip
1405 // has been written into the stencil.
1406 bool stencilClip = fClipState.fClipInStencil &&
1407 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001408 bool stencilChange = fHWStencilClip != stencilClip ||
1409 fHWDrawState.fStencilSettings != *settings ||
1410 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1411 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001412
1413 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001414
bsalomon@google.comd302f142011-03-03 13:54:13 +00001415 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1416 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001417
bsalomon@google.comd302f142011-03-03 13:54:13 +00001418 if (settings->isDisabled()) {
1419 if (stencilClip) {
1420 settings = &gClipStencilSettings;
1421 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001422 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001423
1424 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001425 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001426 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001427 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001428 #if GR_DEBUG
1429 if (!fStencilWrapOpsSupport) {
1430 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1431 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1432 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1433 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1434 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1435 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1436 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1437 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1438 }
1439 #endif
1440 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1441 GrAssert(stencilBits ||
1442 (GrStencilSettings::gDisabled ==
1443 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001444 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1445 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001446
1447 unsigned int frontRef = settings->fFrontFuncRef;
1448 unsigned int frontMask = settings->fFrontFuncMask;
1449 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001450 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001451
1452 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1453
1454 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1455 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1456 } else {
1457 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1458
1459 ConvertStencilFuncAndMask(settings->fFrontFunc,
1460 stencilClip,
1461 clipStencilMask,
1462 userStencilMask,
1463 &frontRef,
1464 &frontMask);
1465 frontWriteMask &= userStencilMask;
1466 }
1467 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001468 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001469 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001470 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001471 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001472 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001473 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001474 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001475 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001476 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001477
1478 unsigned int backRef = settings->fBackFuncRef;
1479 unsigned int backMask = settings->fBackFuncMask;
1480 unsigned int backWriteMask = settings->fBackWriteMask;
1481
1482
1483 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1484 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1485 backFunc = grToGLStencilFunc[settings->fBackFunc];
1486 } else {
1487 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1488 ConvertStencilFuncAndMask(settings->fBackFunc,
1489 stencilClip,
1490 clipStencilMask,
1491 userStencilMask,
1492 &backRef,
1493 &backMask);
1494 backWriteMask &= userStencilMask;
1495 }
1496
twiz@google.com0f31ca72011-03-18 17:38:11 +00001497 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1498 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1499 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1500 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1501 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001502 grToGLStencilOp[settings->fFrontPassOp],
1503 grToGLStencilOp[settings->fFrontPassOp]));
1504
twiz@google.com0f31ca72011-03-18 17:38:11 +00001505 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001506 grToGLStencilOp[settings->fBackPassOp],
1507 grToGLStencilOp[settings->fBackPassOp]));
1508 } else {
1509 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1510 GR_GL(StencilMask(frontWriteMask));
1511 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1512 grToGLStencilOp[settings->fFrontPassOp],
1513 grToGLStencilOp[settings->fFrontPassOp]));
1514 }
1515 }
1516 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001517 fHWStencilClip = stencilClip;
1518 }
1519}
1520
bsalomon@google.comffca4002011-02-22 20:34:01 +00001521bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001522
1523 // GrGpu::setupClipAndFlushState should have already checked this
1524 // and bailed if not true.
1525 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001526
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001527 for (int s = 0; s < kNumStages; ++s) {
1528 bool usingTexture = VertexUsesStage(s, fGeometrySrc.fVertexLayout);
reed@google.comac10a2d2010-12-22 21:39:39 +00001529
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001530 // bind texture and set sampler state
1531 if (usingTexture) {
1532 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001533
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001534 if (NULL != nextTexture) {
bsalomon@google.com316f99232011-01-13 21:28:12 +00001535 // if we created a rt/tex and rendered to it without using a
1536 // texture and now we're texuring from the rt it will still be
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001537 // the last bound texture, but it needs resolving. So keep this
1538 // out of the "last != next" check.
1539 resolveTextureRenderTarget(nextTexture);
reed@google.comac10a2d2010-12-22 21:39:39 +00001540
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001541 if (fHWDrawState.fTextures[s] != nextTexture) {
1542 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001543 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001544 #if GR_COLLECT_STATS
1545 ++fStats.fTextureChngCnt;
1546 #endif
1547 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1548 fHWDrawState.fTextures[s] = nextTexture;
1549 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001550
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001551 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001552 const GrGLTexture::TexParams& oldTexParams =
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001553 nextTexture->getTexParams();
1554 GrGLTexture::TexParams newTexParams;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001555
twiz@google.com0f31ca72011-03-18 17:38:11 +00001556 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1557 GR_GL_NEAREST;
bsalomon@google.com316f99232011-01-13 21:28:12 +00001558 newTexParams.fWrapS =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001559 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
bsalomon@google.com316f99232011-01-13 21:28:12 +00001560 newTexParams.fWrapT =
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001561 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
reed@google.comac10a2d2010-12-22 21:39:39 +00001562
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001563 if (newTexParams.fFilter != oldTexParams.fFilter) {
1564 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001565 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1566 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001567 newTexParams.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001568 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1569 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001570 newTexParams.fFilter));
1571 }
1572 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1573 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001574 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1575 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001576 newTexParams.fWrapS));
1577 }
1578 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1579 setTextureUnit(s);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001580 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1581 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001582 newTexParams.fWrapT));
1583 }
1584 nextTexture->setTexParams(newTexParams);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001585
1586 // The texture matrix has to compensate for texture width/height
1587 // and NPOT-embedded-in-POT
1588 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001589 } else {
1590 GrAssert(!"Rendering with texture vert flag set but no texture");
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001591 return false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001592 }
1593 }
1594 }
1595
1596 flushRenderTarget();
1597
1598 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1599 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1600 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001601 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001602 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001603 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001604 }
1605 }
1606
bsalomon@google.comd302f142011-03-03 13:54:13 +00001607 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1608 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001609 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001610 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001611 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001612 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001613 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001614 }
1615 GR_GL(ColorMask(mask, mask, mask, mask));
1616 }
1617
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001618 if (GR_GL_SUPPORT_DESKTOP) {
1619 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1620 // smooth lines.
1621 if (fDirtyFlags.fRenderTargetChanged ||
1622 (fCurrDrawState.fFlagBits & kAntialias_StateBit) !=
1623 (fHWDrawState.fFlagBits & kAntialias_StateBit)) {
1624 GrGLint msaa = 0;
1625 // only perform query if we know MSAA is supported.
1626 // calling on non-MSAA target caused a crash in one environment,
1627 // though I don't think it should.
1628 if (fAASamples[kHigh_AALevel]) {
1629 GR_GL_GetIntegerv(GR_GL_SAMPLE_BUFFERS, &msaa);
1630 }
1631 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
1632 if (msaa) {
1633 GR_GL(Enable(GR_GL_MULTISAMPLE));
1634 } else {
1635 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1636 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001637 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001638 if (msaa) {
1639 GR_GL(Disable(GR_GL_MULTISAMPLE));
1640 }
1641 GR_GL(Disable(GR_GL_LINE_SMOOTH));
reed@google.comac10a2d2010-12-22 21:39:39 +00001642 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001643 }
1644 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001645
1646 bool blendOff = canDisableBlend();
1647 if (fHWBlendDisabled != blendOff) {
1648 if (blendOff) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001649 GR_GL(Disable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001650 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001651 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +00001652 }
1653 fHWBlendDisabled = blendOff;
1654 }
1655
1656 if (!blendOff) {
1657 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1658 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1659 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1660 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1661 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1662 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1663 }
bsalomon@google.com080773c2011-03-15 19:09:25 +00001664 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1665 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1666 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1667
1668 float c[] = {
1669 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1670 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1671 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1672 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1673 };
1674 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1675 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1676 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001677 }
bsalomon@google.com316f99232011-01-13 21:28:12 +00001678
bsalomon@google.comd302f142011-03-03 13:54:13 +00001679 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1680 switch (fCurrDrawState.fDrawFace) {
1681 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001682 GR_GL(Enable(GR_GL_CULL_FACE));
1683 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001684 break;
1685 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001686 GR_GL(Enable(GR_GL_CULL_FACE));
1687 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001688 break;
1689 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001690 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001691 break;
1692 default:
1693 GrCrash("Unknown draw face.");
1694 }
1695 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1696 }
1697
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001698#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001699 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001700 for (int s = 0; s < kNumStages; ++s) {
1701 GrAssert(!VertexUsesStage(s, fGeometrySrc.fVertexLayout) ||
1702 NULL == fCurrDrawState.fRenderTarget ||
1703 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001704 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001705 fCurrDrawState.fRenderTarget);
1706 }
1707#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001708
reed@google.comac10a2d2010-12-22 21:39:39 +00001709 flushStencil();
1710
bsalomon@google.comd302f142011-03-03 13:54:13 +00001711 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001712 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001713 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001714}
1715
1716void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001717 if (fHWGeometryState.fVertexBuffer != buffer) {
1718 fHWGeometryState.fArrayPtrsDirty = true;
1719 fHWGeometryState.fVertexBuffer = buffer;
1720 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001721}
1722
1723void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
1724 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc &&
1725 buffer == fGeometrySrc.fVertexBuffer));
1726
1727 if (fHWGeometryState.fVertexBuffer == buffer) {
1728 // deleting bound buffer does implied bind to 0
1729 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001730 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001731 }
1732}
1733
1734void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1735 fGeometrySrc.fIndexBuffer = buffer;
1736}
1737
1738void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
1739 GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc &&
1740 buffer == fGeometrySrc.fIndexBuffer));
1741
1742 if (fHWGeometryState.fIndexBuffer == buffer) {
1743 // deleting bound buffer does implied bind to 0
1744 fHWGeometryState.fIndexBuffer = NULL;
1745 }
1746}
1747
reed@google.comac10a2d2010-12-22 21:39:39 +00001748void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1749 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001750 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001751 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001752 }
1753 if (fHWDrawState.fRenderTarget == renderTarget) {
1754 fHWDrawState.fRenderTarget = NULL;
1755 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001756}
1757
1758void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001759 for (int s = 0; s < kNumStages; ++s) {
1760 if (fCurrDrawState.fTextures[s] == texture) {
1761 fCurrDrawState.fTextures[s] = NULL;
1762 }
1763 if (fHWDrawState.fTextures[s] == texture) {
1764 // deleting bound texture does implied bind to 0
1765 fHWDrawState.fTextures[s] = NULL;
1766 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001767 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001768}
1769
reed@google.comac10a2d2010-12-22 21:39:39 +00001770bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001771 GrGLenum* internalFormat,
1772 GrGLenum* format,
1773 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001774 switch (config) {
1775 case GrTexture::kRGBA_8888_PixelConfig:
1776 case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001777 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001778 if (GR_GL_SUPPORT_ES) {
1779 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1780 // format for a BGRA is BGRA not RGBA (as on desktop)
1781 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1782 } else {
1783 *internalFormat = GR_GL_RGBA;
1784 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001785 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001786 break;
1787 case GrTexture::kRGB_565_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001788 *format = GR_GL_RGB;
1789 *internalFormat = GR_GL_RGB;
1790 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001791 break;
1792 case GrTexture::kRGBA_4444_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001793 *format = GR_GL_RGBA;
1794 *internalFormat = GR_GL_RGBA;
1795 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001796 break;
1797 case GrTexture::kIndex_8_PixelConfig:
1798 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001799 *format = GR_GL_PALETTE8_RGBA8;
1800 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001801 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001802 } else {
1803 return false;
1804 }
1805 break;
1806 case GrTexture::kAlpha_8_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001807 *format = GR_GL_ALPHA;
1808 *internalFormat = GR_GL_ALPHA;
1809 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001810 break;
1811 default:
1812 return false;
1813 }
1814 return true;
1815}
1816
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001817void GrGpuGL::setTextureUnit(int unit) {
1818 GrAssert(unit >= 0 && unit < kNumStages);
1819 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001820 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001821 fActiveTextureUnitIdx = unit;
1822 }
1823}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001824
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001825void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001826 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1827 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001828 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1829 }
1830}
1831
reed@google.comac10a2d2010-12-22 21:39:39 +00001832/* On ES the internalFormat and format must match for TexImage and we use
1833 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1834 decide the internalFormat. However, on ES internalFormat for
1835 RenderBufferStorage* has to be a specific format (not a base format like
1836 GL_RGBA).
1837 */
twiz@google.com0f31ca72011-03-18 17:38:11 +00001838bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001839 switch (config) {
1840 case GrTexture::kRGBA_8888_PixelConfig:
1841 case GrTexture::kRGBX_8888_PixelConfig:
1842 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001843 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001844 return true;
1845 } else {
1846 return false;
1847 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001848 case GrTexture::kRGB_565_PixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001849 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1850 // with FBO extension desktop GL has
1851 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001852 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001853 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001854 case GrTexture::kRGBA_4444_PixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001855 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001856 return true;
1857 default:
1858 return false;
1859 }
1860}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001861
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001862void GrGpuGL::resetDirtyFlags() {
1863 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1864}
1865
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001866void GrGpuGL::setBuffers(bool indexed,
1867 int* extraVertexOffset,
1868 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001869
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001870 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001871
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001872 GrGLVertexBuffer* vbuf;
1873 switch (fGeometrySrc.fVertexSrc) {
1874 case kBuffer_GeometrySrcType:
1875 *extraVertexOffset = 0;
1876 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
1877 break;
1878 case kArray_GeometrySrcType:
1879 case kReserved_GeometrySrcType:
1880 finalizeReservedVertices();
1881 *extraVertexOffset = fCurrPoolStartVertex;
1882 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
1883 break;
1884 default:
1885 vbuf = NULL; // suppress warning
1886 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001887 }
1888
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001889 GrAssert(NULL != vbuf);
1890 GrAssert(!vbuf->isLocked());
1891 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001892 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001893 fHWGeometryState.fArrayPtrsDirty = true;
1894 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001895 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001896
1897 if (indexed) {
1898 GrAssert(NULL != extraIndexOffset);
1899
1900 GrGLIndexBuffer* ibuf;
1901 switch (fGeometrySrc.fIndexSrc) {
1902 case kBuffer_GeometrySrcType:
1903 *extraIndexOffset = 0;
1904 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
1905 break;
1906 case kArray_GeometrySrcType:
1907 case kReserved_GeometrySrcType:
1908 finalizeReservedIndices();
1909 *extraIndexOffset = fCurrPoolStartIndex;
1910 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
1911 break;
1912 default:
1913 ibuf = NULL; // suppress warning
1914 GrCrash("Unknown geometry src type!");
1915 }
1916
1917 GrAssert(NULL != ibuf);
1918 GrAssert(!ibuf->isLocked());
1919 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001920 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001921 fHWGeometryState.fIndexBuffer = ibuf;
1922 }
1923 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001924}