blob: c63c7669feca70dcfcf3744d7da15c5ea63d0ea1 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
bsalomon@google.com1da07462011-03-10 14:51:57 +00002 Copyright 2011 Google Inc.
reed@google.comac10a2d2010-12-22 21:39:39 +00003
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#include "GrGpuGL.h"
18#include "GrMemory.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000019
twiz@google.com0f31ca72011-03-18 17:38:11 +000020static const GrGLuint GR_MAX_GLUINT = ~0;
21static const GrGLint GR_INVAL_GLINT = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000022
bsalomon@google.com316f99232011-01-13 21:28:12 +000023// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000024// mucking with the state of any of the stages.
bsalomon@google.com316f99232011-01-13 21:28:12 +000025static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000026
reed@google.comac10a2d2010-12-22 21:39:39 +000027#define SKIP_CACHE_CHECK true
28
twiz@google.com0f31ca72011-03-18 17:38:11 +000029static const GrGLenum gXfermodeCoeff2Blend[] = {
30 GR_GL_ZERO,
31 GR_GL_ONE,
32 GR_GL_SRC_COLOR,
33 GR_GL_ONE_MINUS_SRC_COLOR,
34 GR_GL_DST_COLOR,
35 GR_GL_ONE_MINUS_DST_COLOR,
36 GR_GL_SRC_ALPHA,
37 GR_GL_ONE_MINUS_SRC_ALPHA,
38 GR_GL_DST_ALPHA,
39 GR_GL_ONE_MINUS_DST_ALPHA,
40 GR_GL_CONSTANT_COLOR,
41 GR_GL_ONE_MINUS_CONSTANT_COLOR,
42 GR_GL_CONSTANT_ALPHA,
43 GR_GL_ONE_MINUS_CONSTANT_ALPHA,
reed@google.comac10a2d2010-12-22 21:39:39 +000044};
45
bsalomon@google.com080773c2011-03-15 19:09:25 +000046bool GrGpuGL::BlendCoefReferencesConstant(GrBlendCoeff coeff) {
47 static const bool gCoeffReferencesBlendConst[] = {
48 false,
49 false,
50 false,
51 false,
52 false,
53 false,
54 false,
55 false,
56 false,
57 false,
58 true,
59 true,
60 true,
61 true,
62 };
63 return gCoeffReferencesBlendConst[coeff];
64 GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
65}
66
67GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
68GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
69GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
70GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
71GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
72GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
73GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
74GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
75GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
76GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
77GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
78GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
79GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
80GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
81
82GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
83
reed@google.comac10a2d2010-12-22 21:39:39 +000084///////////////////////////////////////////////////////////////////////////////
85
bsalomon@google.comd302f142011-03-03 13:54:13 +000086void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
87 GrSamplerState::SampleMode mode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000088 GrMatrix* matrix) {
89 GrAssert(NULL != texture);
90 GrAssert(NULL != matrix);
91 if (GR_Scalar1 != texture->contentScaleX() ||
92 GR_Scalar1 != texture->contentScaleY()) {
93 if (GrSamplerState::kRadial_SampleMode == mode) {
94 GrMatrix scale;
95 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
96 matrix->postConcat(scale);
97 } else if (GrSamplerState::kNormal_SampleMode == mode) {
98 GrMatrix scale;
99 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
100 matrix->postConcat(scale);
101 } else {
102 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
103 }
104 }
105 GrGLTexture::Orientation orientation = texture->orientation();
106 if (GrGLTexture::kBottomUp_Orientation == orientation) {
107 GrMatrix invY;
108 invY.setAll(GR_Scalar1, 0, 0,
109 0, -GR_Scalar1, GR_Scalar1,
110 0, 0, GrMatrix::I()[8]);
111 matrix->postConcat(invY);
112 } else {
113 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
114 }
115}
116
bsalomon@google.comd302f142011-03-03 13:54:13 +0000117bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000118 const GrSamplerState& sampler) {
119 GrAssert(NULL != texture);
120 if (!sampler.getMatrix().isIdentity()) {
121 return false;
122 }
123 if (GR_Scalar1 != texture->contentScaleX() ||
124 GR_Scalar1 != texture->contentScaleY()) {
125 return false;
126 }
127 GrGLTexture::Orientation orientation = texture->orientation();
128 if (GrGLTexture::kBottomUp_Orientation == orientation) {
129 return false;
130 } else {
131 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
132 }
133 return true;
134}
135
136///////////////////////////////////////////////////////////////////////////////
137
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000138static bool gPrintStartupSpew;
139
twiz@google.com59a190b2011-03-14 21:23:01 +0000140static bool fbo_test(int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000141
twiz@google.com0f31ca72011-03-18 17:38:11 +0000142 GrGLint savedFBO;
143 GrGLint savedTexUnit;
144 GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000145 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000146
twiz@google.com0f31ca72011-03-18 17:38:11 +0000147 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000148
twiz@google.com0f31ca72011-03-18 17:38:11 +0000149 GrGLuint testFBO;
twiz@google.com59a190b2011-03-14 21:23:01 +0000150 GR_GL(GenFramebuffers(1, &testFBO));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000151 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000152 GrGLuint testRTTex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 GR_GL(GenTextures(1, &testRTTex));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000154 GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000155 // some implementations require texture to be mip-map complete before
156 // FBO with level 0 bound as color attachment will be framebuffer complete.
twiz@google.com0f31ca72011-03-18 17:38:11 +0000157 GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
158 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
159 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
160 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000161 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000162 GR_GL_TEXTURE_2D, testRTTex, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000163 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000164 GR_GL(DeleteFramebuffers(1, &testFBO));
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000166
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000167 GR_GL(ActiveTexture(savedTexUnit));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000168 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000169
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000170 return status == GR_GL_FRAMEBUFFER_COMPLETE;
reed@google.comac10a2d2010-12-22 21:39:39 +0000171}
172
reed@google.comac10a2d2010-12-22 21:39:39 +0000173GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000174
reed@google.comeeeb5a02010-12-23 15:12:59 +0000175 if (gPrintStartupSpew) {
176 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
177 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000178 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000179 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000180 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000181 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000182 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000183 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000184 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000185 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000186 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000187
188 GrGLClearErr();
189
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000190 resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000191
twiz@google.com0f31ca72011-03-18 17:38:11 +0000192 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000193 // check FS and fixed-function texture unit limits
194 // we only use textures in the fragment stage currently.
195 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000196 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
197 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
198 GrAssert(maxTextureUnits > kNumStages);
199 }
200 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
201 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
202 GrAssert(maxTextureUnits > kNumStages);
203 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000204
reed@google.comac10a2d2010-12-22 21:39:39 +0000205 ////////////////////////////////////////////////////////////////////////////
206 // Check for supported features.
207
208 int major, minor;
209 gl_version(&major, &minor);
210
twiz@google.com0f31ca72011-03-18 17:38:11 +0000211 GrGLint numFormats;
212 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
213 GrAutoSTMalloc<10, GrGLint> formats(numFormats);
214 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000216 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000217 f8bitPaletteSupport = true;
218 break;
219 }
220 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000221
222 if (gPrintStartupSpew) {
223 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
224 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000225
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000226 GR_STATIC_ASSERT(0 == kNone_GrAALevel);
227 GR_STATIC_ASSERT(1 == kLow_GrAALevel);
228 GR_STATIC_ASSERT(2 == kMed_GrAALevel);
229 GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
reed@google.comac10a2d2010-12-22 21:39:39 +0000230
231 memset(fAASamples, 0, sizeof(fAASamples));
232 fMSFBOType = kNone_MSFBO;
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000233 if (GR_GL_SUPPORT_ES) {
234 if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000235 // chrome's extension is equivalent to the EXT msaa
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000236 // and fbo_blit extensions.
237 fMSFBOType = kDesktopEXT_MSFBO;
238 } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
239 fMSFBOType = kAppleES_MSFBO;
240 }
241 } else {
242 GrAssert(GR_GL_SUPPORT_DESKTOP);
243 if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
244 fMSFBOType = kDesktopARB_MSFBO;
245 } else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
246 has_gl_extension("GL_EXT_framebuffer_blit")) {
247 fMSFBOType = kDesktopEXT_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000248 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000249 }
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000250 if (gPrintStartupSpew) {
251 switch (fMSFBOType) {
252 case kNone_MSFBO:
253 GrPrintf("MSAA Support: NONE\n");
254 break;
255 case kDesktopARB_MSFBO:
256 GrPrintf("MSAA Support: DESKTOP ARB.\n");
257 break;
258 case kDesktopEXT_MSFBO:
259 GrPrintf("MSAA Support: DESKTOP EXT.\n");
260 break;
261 case kAppleES_MSFBO:
262 GrPrintf("MSAA Support: APPLE ES.\n");
263 break;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000264 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000265 }
266
267 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000268 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000269 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000270 if (maxSamples > 1 ) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000271 fAASamples[kNone_GrAALevel] = 0;
272 fAASamples[kLow_GrAALevel] = GrMax(2,
273 GrFixedFloorToInt((GR_FixedHalf) *
274 maxSamples));
275 fAASamples[kMed_GrAALevel] = GrMax(2,
276 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
277 maxSamples));
278 fAASamples[kHigh_GrAALevel] = maxSamples;
reed@google.comac10a2d2010-12-22 21:39:39 +0000279 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000280 if (gPrintStartupSpew) {
281 GrPrintf("\tMax Samples: %d\n", maxSamples);
282 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000283 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +0000284 fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000285
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000286 if (GR_GL_SUPPORT_DESKTOP) {
287 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
288 has_gl_extension("GL_EXT_stencil_wrap");
289 } else {
290 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
291 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000292 if (gPrintStartupSpew) {
293 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
294 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000295
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000296 if (GR_GL_SUPPORT_DESKTOP) {
297 // we could also look for GL_ATI_separate_stencil extension or
298 // GL_EXT_stencil_two_side but they use different function signatures
299 // than GL2.0+ (and than each other).
300 fTwoSidedStencilSupport = (major >= 2);
301 // supported on GL 1.4 and higher or by extension
302 fStencilWrapOpsSupport = (major > 1) ||
303 ((1 == major) && (minor >= 4)) ||
304 has_gl_extension("GL_EXT_stencil_wrap");
305 } else {
306 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
307 // an ES1 extension.
308 fTwoSidedStencilSupport = (major >= 2);
309 // stencil wrap support is in ES2, ES1 requires extension.
310 fStencilWrapOpsSupport = (major > 1) ||
311 has_gl_extension("GL_OES_stencil_wrap");
312 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000313 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000314 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
315 (fTwoSidedStencilSupport ? "YES" : "NO"),
316 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000317 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000318
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000319 if (GR_GL_SUPPORT_DESKTOP) {
320 fRGBA8Renderbuffer = true;
321 } else {
322 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
323 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000324 if (gPrintStartupSpew) {
325 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
326 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000327
328
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000329 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000330 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000331 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
332 }
333 }
334
335 if (GR_GL_SUPPORT_DESKTOP) {
336 fBufferLockSupport = true; // we require VBO support and the desktop VBO
337 // extension includes glMapBuffer.
338 } else {
339 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
340 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000341
reed@google.comeeeb5a02010-12-23 15:12:59 +0000342 if (gPrintStartupSpew) {
343 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
344 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000345
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000346 if (GR_GL_SUPPORT_DESKTOP) {
347 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
348 fNPOTTextureTileSupport = true;
349 fNPOTTextureSupport = true;
350 } else {
351 fNPOTTextureTileSupport = false;
352 fNPOTTextureSupport = false;
353 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000354 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000355 if (major >= 2) {
356 fNPOTTextureSupport = true;
357 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
358 } else {
359 fNPOTTextureSupport =
360 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
361 fNPOTTextureTileSupport = false;
362 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000363 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000364
bsalomon@google.com205d4602011-04-25 12:43:45 +0000365 fAALineSupport = GR_GL_SUPPORT_DESKTOP;
366
reed@google.comac10a2d2010-12-22 21:39:39 +0000367 ////////////////////////////////////////////////////////////////////////////
368 // Experiments to determine limitations that can't be queried. TODO: Make
369 // these a preprocess that generate some compile time constants.
370
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000371 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000372
twiz@google.com59a190b2011-03-14 21:23:01 +0000373 bool simpleFBOSuccess = fbo_test(128, 128);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000374 if (gPrintStartupSpew) {
375 if (!simpleFBOSuccess) {
376 GrPrintf("FBO Sanity Test: FAILED\n");
377 } else {
378 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000379 }
380 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000381 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000382
reed@google.comac10a2d2010-12-22 21:39:39 +0000383 /* Experimentation has found that some GLs that support NPOT textures
384 do not support FBOs with a NPOT texture. They report "unsupported" FBO
385 status. I don't know how to explicitly query for this. Do an
386 experiment. Note they may support NPOT with a renderbuffer but not a
387 texture. Presumably, the implementation bloats the renderbuffer
388 internally to the next POT.
389 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000390 bool fNPOTRenderTargetSupport = false;
391 if (fNPOTTextureSupport) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000392 fNPOTRenderTargetSupport = fbo_test(200, 200);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000393 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000394
bsalomon@google.com0748f212011-02-01 22:56:16 +0000395 if (gPrintStartupSpew) {
396 if (fNPOTTextureSupport) {
397 GrPrintf("NPOT textures supported\n");
398 if (fNPOTTextureTileSupport) {
399 GrPrintf("NPOT texture tiling supported\n");
400 } else {
401 GrPrintf("NPOT texture tiling NOT supported\n");
402 }
403 if (fNPOTRenderTargetSupport) {
404 GrPrintf("NPOT render targets supported\n");
405 } else {
406 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000407 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000408 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000409 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000410 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000411 }
412
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000413 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
414
reed@google.comac10a2d2010-12-22 21:39:39 +0000415 /* The iPhone 4 has a restriction that for an FBO with texture color
416 attachment with height <= 8 then the width must be <= height. Here
417 we look for such a limitation.
418 */
419 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000420 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000421 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000422 // fbo_test creates FBOs with texture bound to the color attachment
423 maxRenderSize = GrMin(maxRenderSize, fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000424
reed@google.comeeeb5a02010-12-23 15:12:59 +0000425 if (gPrintStartupSpew) {
426 GrPrintf("Small height FBO texture experiments\n");
427 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000428
twiz@google.com0f31ca72011-03-18 17:38:11 +0000429 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
430 GrGLuint w = maxRenderSize;
431 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000432 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000433 if (gPrintStartupSpew) {
434 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
435 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000436 fMinRenderTargetHeight = i;
437 break;
438 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000439 if (gPrintStartupSpew) {
440 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
441 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000442 }
443 }
444 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
445
reed@google.comeeeb5a02010-12-23 15:12:59 +0000446 if (gPrintStartupSpew) {
447 GrPrintf("Small width FBO texture experiments\n");
448 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000449 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000450 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
451 GrGLuint w = i;
452 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000453 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000454 if (gPrintStartupSpew) {
455 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
456 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000457 fMinRenderTargetWidth = i;
458 break;
459 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000460 if (gPrintStartupSpew) {
461 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
462 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000463 }
464 }
465 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
reed@google.comac10a2d2010-12-22 21:39:39 +0000466}
467
468GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000469}
470
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000471void GrGpuGL::resetContext() {
472 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000473 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000474 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000475
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000476 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000477 GR_GL(Disable(GR_GL_DEPTH_TEST));
478 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000479
twiz@google.com0f31ca72011-03-18 17:38:11 +0000480 GR_GL(Disable(GR_GL_CULL_FACE));
481 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000482 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000483
twiz@google.com0f31ca72011-03-18 17:38:11 +0000484 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000485 if (GR_GL_SUPPORT_DESKTOP) {
486 GR_GL(Disable(GR_GL_LINE_SMOOTH));
487 GR_GL(Disable(GR_GL_POINT_SMOOTH));
488 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000489 fHWAAState.fMSAAEnabled = false;
490 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000491 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000492
twiz@google.com0f31ca72011-03-18 17:38:11 +0000493 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000494 fHWDrawState.fFlagBits = 0;
495
reed@google.comac10a2d2010-12-22 21:39:39 +0000496 // we only ever use lines in hairline mode
497 GR_GL(LineWidth(1));
498
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000499 // invalid
500 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000501
reed@google.comac10a2d2010-12-22 21:39:39 +0000502 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000503 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
504 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000505
506 fHWDrawState.fBlendConstant = 0x00000000;
507 GR_GL(BlendColor(0,0,0,0));
508
reed@google.comac10a2d2010-12-22 21:39:39 +0000509 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000510
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000511 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000512
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000513 for (int s = 0; s < kNumStages; ++s) {
514 fHWDrawState.fTextures[s] = NULL;
515 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
516 -GR_ScalarMax,
517 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000518
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000519 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000520 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000521
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000522 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000523 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000524 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000525 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000526
bsalomon@google.comd302f142011-03-03 13:54:13 +0000527 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000528 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000529 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000530
531 fHWGeometryState.fIndexBuffer = NULL;
532 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000533
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000534 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000535
twiz@google.com0f31ca72011-03-18 17:38:11 +0000536 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000537 fHWDrawState.fRenderTarget = NULL;
538}
539
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000540GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
541
542 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
543 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
544 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
545 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
546
547 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
548 if (isRenderTarget) {
549 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
550 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
551 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
552 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
553 } else {
554 GrAssert(!isTexture); // this should have been filtered by GrContext
555 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
556 }
557 } else {
558 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
559 }
560 // we don't know what the RB ids are without glGets and we don't care
561 // since we aren't responsible for deleting them.
562 rtIDs.fStencilRenderbufferID = 0;
563 rtIDs.fMSColorRenderbufferID = 0;
564
565 rtIDs.fOwnIDs = false;
566 } else {
567 rtIDs.reset();
568 }
569
570 if (isTexture) {
571 GrGLTexture::GLTextureDesc texDesc;
572 GrGLenum dontCare;
573 if (!canBeTexture(desc.fConfig, &dontCare,
574 &texDesc.fUploadFormat,
575 &texDesc.fUploadType)) {
576 return NULL;
577 }
578
579 GrGLTexture::TexParams params;
580
581 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
582 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
583
584 texDesc.fFormat = texDesc.fFormat;
585 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
586 texDesc.fStencilBits = desc.fStencilBits;
587 texDesc.fTextureID = desc.fPlatformTexture;
588 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
589 texDesc.fOwnsID = false;
590
591 params.invalidate(); // rather than do glGets.
592
593 return new GrGLTexture(this, texDesc, rtIDs, params);
594 } else {
595 GrGLIRect viewport;
596 viewport.fLeft = 0;
597 viewport.fBottom = 0;
598 viewport.fWidth = desc.fWidth;
599 viewport.fHeight = desc.fHeight;
600
601 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
602 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
603 viewport, NULL);
604 }
605}
606
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000607GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(
reed@google.comac10a2d2010-12-22 21:39:39 +0000608 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000609 int stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000610 bool isMultisampled,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000611 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000612 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000613 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
614 rtIDs.fStencilRenderbufferID = 0;
615 rtIDs.fMSColorRenderbufferID = 0;
616 rtIDs.fTexFBOID = 0;
617 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000618 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000619
620 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000621 viewport.fLeft = 0;
622 viewport.fBottom = 0;
623 viewport.fWidth = width;
624 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000625
twiz@google.com0f31ca72011-03-18 17:38:11 +0000626 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
627 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000628
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000629 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
630 isMultisampled, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000631}
632
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000633GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000634
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000635 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000636
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000637 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000638 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
639 rtIDs.fMSColorRenderbufferID = 0;
640 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000641
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000642 GrGLIRect viewport;
643 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000644 GrGLuint stencilBits;
645 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000646
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000647 GrGLint samples;
648 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
649
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000650 rtIDs.fOwnIDs = false;
651
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000652 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
653 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000654}
655
bsalomon@google.com5782d712011-01-21 21:03:59 +0000656///////////////////////////////////////////////////////////////////////////////
657
twiz@google.com0f31ca72011-03-18 17:38:11 +0000658static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000659
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000660struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000661 GrGLenum fEnum;
662 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000663 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000664};
665
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000666const StencilFormat* GrGLStencilFormats() {
667 // defines stencil formats from more to less preferred
668 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000669 {GR_GL_STENCIL_INDEX8, 8, false},
670 {GR_GL_STENCIL_INDEX16, 16, false},
671 {GR_GL_DEPTH24_STENCIL8, 8, true },
672 {GR_GL_STENCIL_INDEX4, 4, false},
673 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
674 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
675 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000676 };
677
678 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000679 {GR_GL_STENCIL_INDEX8, 8, false},
680 {GR_GL_DEPTH24_STENCIL8, 8, true },
681 {GR_GL_STENCIL_INDEX4, 4, false},
682 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000683 };
684
685 if (GR_GL_SUPPORT_DESKTOP) {
686 return desktopStencilFormats;
687 } else {
688 return esStencilFormats;
689 }
690}
691
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000692// good to set a break-point here to know when createTexture fails
693static GrTexture* return_null_texture() {
694// GrAssert(!"null texture");
695 return NULL;
696}
697
698#if GR_DEBUG
699static size_t as_size_t(int x) {
700 return x;
701}
702#endif
703
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000704GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000705 const void* srcData,
706 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000707
708#if GR_COLLECT_STATS
709 ++fStats.fTextureCreateCnt;
710#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000711
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000712 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000713
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000714 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000715 GR_GL_NEAREST,
716 GR_GL_CLAMP_TO_EDGE,
717 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000718 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000719
reed@google.comac10a2d2010-12-22 21:39:39 +0000720 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000721 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000722
723 glDesc.fContentWidth = desc.fWidth;
724 glDesc.fContentHeight = desc.fHeight;
725 glDesc.fAllocWidth = desc.fWidth;
726 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000727 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000728 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000729 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000730
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000731 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000732 if (!canBeTexture(desc.fFormat,
733 &internalFormat,
734 &glDesc.fUploadFormat,
735 &glDesc.fUploadType)) {
736 return return_null_texture();
737 }
738
739 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000740 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000741 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000742 GrPrintf("AA RT requested but not supported on this platform.");
743 }
744
745 GR_GL(GenTextures(1, &glDesc.fTextureID));
746 if (!glDesc.fTextureID) {
747 return return_null_texture();
748 }
749
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000750 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000751
reed@google.com5e762232011-04-04 18:15:49 +0000752 // in case we need a temporary, trimmed copy of the src pixels
753 GrAutoSMalloc<128 * 128> trimStorage;
754
reed@google.comac10a2d2010-12-22 21:39:39 +0000755 /*
756 * check if our srcData has extra bytes past each row. If so, we need
757 * to trim those off here, since GL doesn't let us pass the rowBytes as
758 * a parameter to glTexImage2D
759 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000760 if (GR_GL_SUPPORT_DESKTOP) {
761 if (srcData) {
762 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
763 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000764 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000765 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000766 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
767 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000768 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000769 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000770 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000771 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000772 for (uint32_t y = 0; y < desc.fHeight; y++) {
773 memcpy(dst, src, trimRowBytes);
774 src += rowBytes;
775 dst += trimRowBytes;
776 }
777 // now point srcData to our trimmed version
778 srcData = trimStorage.get();
779 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000780 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000781
reed@google.comac10a2d2010-12-22 21:39:39 +0000782 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000783 if (!this->npotRenderTargetSupport()) {
784 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
785 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
786 }
787
reed@google.comac10a2d2010-12-22 21:39:39 +0000788 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
789 glDesc.fAllocWidth);
790 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
791 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000792 } else if (!this->npotTextureSupport()) {
793 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
794 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000795 }
796
twiz@google.com0f31ca72011-03-18 17:38:11 +0000797 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
798 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
799 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000800 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000801 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
802 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000803 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000804 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
805 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000806 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000807 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
808 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000809 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000810
twiz@google.com0f31ca72011-03-18 17:38:11 +0000811 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000812 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000813 supports8BitPalette()) {
814 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
815 GrAssert(desc.fWidth == glDesc.fAllocWidth);
816 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000817 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000818 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000819 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000820 glDesc.fAllocWidth, glDesc.fAllocHeight,
821 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000822 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000823 } else {
824 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
825 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000826 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000827 glDesc.fAllocWidth, glDesc.fAllocHeight,
828 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000829 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000830 desc.fHeight, glDesc.fUploadFormat,
831 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000832 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000833
834 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
835 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
836 uint32_t maxTexels = extraW * extraH;
837 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
838 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
839
840 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
841
842 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
843 if (extraH) {
844 uint8_t* lastRowStart = (uint8_t*) srcData +
845 (desc.fHeight - 1) * rowSize;
846 uint8_t* extraRowStart = (uint8_t*)texels.get();
847
848 for (uint32_t i = 0; i < extraH; ++i) {
849 memcpy(extraRowStart, lastRowStart, rowSize);
850 extraRowStart += rowSize;
851 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000852 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000853 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
854 texels.get()));
855 }
856 if (extraW) {
857 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
858 uint8_t* extraTexel = (uint8_t*)texels.get();
859 for (uint32_t j = 0; j < desc.fHeight; ++j) {
860 for (uint32_t i = 0; i < extraW; ++i) {
861 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
862 extraTexel += glDesc.fUploadByteCount;
863 }
864 edgeTexel += rowSize;
865 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000866 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000867 desc.fHeight, glDesc.fUploadFormat,
868 glDesc.fUploadType, texels.get()));
869 }
870 if (extraW && extraH) {
871 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
872 - glDesc.fUploadByteCount;
873 uint8_t* extraTexel = (uint8_t*)texels.get();
874 for (uint32_t i = 0; i < extraW*extraH; ++i) {
875 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
876 extraTexel += glDesc.fUploadByteCount;
877 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000878 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000879 extraW, extraH, glDesc.fUploadFormat,
880 glDesc.fUploadType, texels.get()));
881 }
882
883 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000884 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000885 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
886 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000887 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000888 }
889 }
890
891 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
892
893 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
894 rtIDs.fStencilRenderbufferID = 0;
895 rtIDs.fMSColorRenderbufferID = 0;
896 rtIDs.fRTFBOID = 0;
897 rtIDs.fTexFBOID = 0;
898 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000899 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000900
901 if (renderTarget) {
902#if GR_COLLECT_STATS
903 ++fStats.fRenderTargetCreateCnt;
904#endif
905 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000906 GrGLenum status;
907 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000908
909 // If need have both RT flag and srcData we have
910 // to invert the data before uploading because FBO
911 // will be rendered bottom up
912 GrAssert(NULL == srcData);
913 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
914
twiz@google.com59a190b2011-03-14 21:23:01 +0000915 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000916 GrAssert(rtIDs.fTexFBOID);
917
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000918 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000919 // to one and then resolve to the texture bound to the other.
920 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000921 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000923 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000924 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
925 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000926 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000927 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000928 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
929 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000930 return return_null_texture();
931 }
932 } else {
933 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
934 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000935 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000936 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000937 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000938 }
939
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000940 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000941 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000942 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000943 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000944
twiz@google.com0f31ca72011-03-18 17:38:11 +0000945 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000946
947 const StencilFormat* stencilFormats = GrGLStencilFormats();
948 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000949 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000950 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000951 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000952 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000953 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000954 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000955 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000956 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000957 glDesc.fAllocWidth,
958 glDesc.fAllocHeight));
959 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000960 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000961 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000962 glDesc.fAllocWidth,
963 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000964 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000965 err = GrGLGetGLInterface()->fGetError();
966 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000967 continue;
968 }
969 }
970 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
971 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000972 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000973 rtIDs.fMSColorRenderbufferID));
974 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000975 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000976 samples,
977 msColorRenderbufferFormat,
978 glDesc.fAllocWidth,
979 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000980 err = GrGLGetGLInterface()->fGetError();
981 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000982 continue;
983 }
984 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000985 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000986
987#if GR_COLLECT_STATS
988 ++fStats.fRenderTargetChngCnt;
989#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000990 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
991 GR_GL_COLOR_ATTACHMENT0,
992 GR_GL_TEXTURE_2D,
993 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000994 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000995 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
996 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000997 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
998 status, desc.fWidth, desc.fHeight);
999 continue;
1000 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001001 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001002 #if GR_COLLECT_STATS
1003 ++fStats.fRenderTargetChngCnt;
1004 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001005 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1006 GR_GL_COLOR_ATTACHMENT0,
1007 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001008 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001009
1010 }
1011 if (rtIDs.fStencilRenderbufferID) {
1012 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001013 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1014 GR_GL_STENCIL_ATTACHMENT,
1015 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001016 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001017 // if it is a packed format bind to depth also, otherwise
1018 // we may get an unsupported fbo completeness result
1019 if (stencilFormats[i].fPacked) {
1020 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1021 GR_GL_DEPTH_ATTACHMENT,
1022 GR_GL_RENDERBUFFER,
1023 rtIDs.fStencilRenderbufferID));
1024 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001025 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001026 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001027
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001028 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001029 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1030 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001031 // undo the depth bind
1032 if (rtIDs.fStencilRenderbufferID &&
1033 stencilFormats[i].fPacked) {
1034 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1035 GR_GL_DEPTH_ATTACHMENT,
1036 GR_GL_RENDERBUFFER,
1037 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001038 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001039 continue;
1040 }
1041 // we're successful!
1042 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001043 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001044 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001045 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001046 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001047 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001048 }
1049 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001050 break;
1051 }
1052 if (failed) {
1053 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001054 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001055 }
1056 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001057 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001058 }
1059 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001060 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001061 }
1062 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001063 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001064 }
1065 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1066 return return_null_texture();
1067 }
1068 }
1069#ifdef TRACE_TEXTURE_CREATION
1070 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1071 tex->fTextureID, width, height, tex->fUploadByteCount);
1072#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001073 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001074
1075 if (0 != rtIDs.fTexFBOID) {
1076 GrRenderTarget* rt = tex->asRenderTarget();
1077 // We've messed with FBO state but may not have set the correct viewport
1078 // so just dirty the rendertarget state to force a resend.
1079 fHWDrawState.fRenderTarget = NULL;
1080
1081 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001082 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001083 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1084 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001085 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001086 fCurrDrawState.fRenderTarget = rtSave;
1087 }
1088 }
1089 return tex;
1090}
1091
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001092GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001093 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 GR_GL(GenBuffers(1, &id));
1095 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001096 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001097 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001098 GrGLClearErr();
1099 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001100 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1101 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1102 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001103 GR_GL(DeleteBuffers(1, &id));
1104 // deleting bound buffer does implicit bind to 0
1105 fHWGeometryState.fVertexBuffer = NULL;
1106 return NULL;
1107 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001108 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001109 size, dynamic);
1110 fHWGeometryState.fVertexBuffer = vertexBuffer;
1111 return vertexBuffer;
1112 }
1113 return NULL;
1114}
1115
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001116GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001117 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001118 GR_GL(GenBuffers(1, &id));
1119 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001120 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001121 GrGLClearErr();
1122 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001123 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1124 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1125 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001126 GR_GL(DeleteBuffers(1, &id));
1127 // deleting bound buffer does implicit bind to 0
1128 fHWGeometryState.fIndexBuffer = NULL;
1129 return NULL;
1130 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001131 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001132 size, dynamic);
1133 fHWGeometryState.fIndexBuffer = indexBuffer;
1134 return indexBuffer;
1135 }
1136 return NULL;
1137}
1138
reed@google.comac10a2d2010-12-22 21:39:39 +00001139void GrGpuGL::flushScissor(const GrIRect* rect) {
1140 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001141 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001142 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001143
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001144 GrGLIRect scissor;
1145 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001146 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001147 rect->width(), rect->height());
1148 if (scissor.contains(vp)) {
1149 rect = NULL;
1150 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001151 }
1152
1153 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001154 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001155 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 fHWBounds.fScissorRect = scissor;
1157 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001158 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001159 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001160 fHWBounds.fScissorEnabled = true;
1161 }
1162 } else {
1163 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001164 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001165 fHWBounds.fScissorEnabled = false;
1166 }
1167 }
1168}
1169
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001170void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001171 if (NULL == fCurrDrawState.fRenderTarget) {
1172 return;
1173 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001174 GrIRect r;
1175 if (NULL != rect) {
1176 // flushScissor expects rect to be clipped to the target.
1177 r = *rect;
1178 GrIRect rtRect(0, 0,
1179 fCurrDrawState.fRenderTarget->width(),
1180 fCurrDrawState.fRenderTarget->height());
1181 if (r.intersectWith(rtRect)) {
1182 rect = &r;
1183 } else {
1184 return;
1185 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001186 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001187 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001188 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001189 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001190 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001191 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1192 GrColorUnpackG(color)/255.f,
1193 GrColorUnpackB(color)/255.f,
1194 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001195 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001196}
1197
bsalomon@google.com398109c2011-04-14 18:40:27 +00001198void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001199 if (NULL == fCurrDrawState.fRenderTarget) {
1200 return;
1201 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001202
1203 this->flushRenderTarget(&GrIRect::EmptyIRect());
1204
reed@google.comac10a2d2010-12-22 21:39:39 +00001205 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001206 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001207 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001208 }
1209 GR_GL(StencilMask(mask));
1210 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001211 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001212 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001213}
1214
bsalomon@google.com398109c2011-04-14 18:40:27 +00001215void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001216 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001217#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001218 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001219 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001220 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001221#else
1222 // we could just clear the clip bit but when we go through
1223 // angle a partial stencil mask will cause clears to be
1224 // turned into draws. Our contract on GrDrawTarget says that
1225 // changing the clip between stencil passes may or may not
1226 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001227 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001228#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001229 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001230 flushScissor(&rect);
1231 GR_GL(StencilMask(clipStencilMask));
1232 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001233 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001234 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001235}
1236
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001237void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001238 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001239}
1240
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001241bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1242 int left, int top, int width, int height,
1243 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001244 GrGLenum internalFormat; // we don't use this for glReadPixels
1245 GrGLenum format;
1246 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001247 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1248 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001249 }
1250 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1251 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1252 switch (tgt->getResolveType()) {
1253 case GrGLRenderTarget::kCantResolve_ResolveType:
1254 return false;
1255 case GrGLRenderTarget::kAutoResolves_ResolveType:
1256 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1257 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001258 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001259 break;
1260 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001261 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001262 // we don't track the state of the READ FBO ID.
1263 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1264 break;
1265 default:
1266 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001267 }
1268
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001269 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001270
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001271 // the read rect is viewport-relative
1272 GrGLIRect readRect;
1273 readRect.setRelativeTo(glvp, left, top, width, height);
1274 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001275 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001276 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001277
1278 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1279 // API presents top-to-bottom
1280 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001281 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001282 GrAutoMalloc rowStorage(stride);
1283 void* tmp = rowStorage.get();
1284
1285 const int halfY = height >> 1;
1286 char* top = reinterpret_cast<char*>(buffer);
1287 char* bottom = top + (height - 1) * stride;
1288 for (int y = 0; y < halfY; y++) {
1289 memcpy(tmp, top, stride);
1290 memcpy(top, bottom, stride);
1291 memcpy(bottom, tmp, stride);
1292 top += stride;
1293 bottom -= stride;
1294 }
1295 }
1296 return true;
1297}
1298
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001299void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001300
1301 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1302
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001303 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001304 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001305 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001306 #if GR_COLLECT_STATS
1307 ++fStats.fRenderTargetChngCnt;
1308 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001309 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001310 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1311 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001312 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1313 }
1314 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001315 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001316 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001317 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001318 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001319 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001320 fHWBounds.fViewportRect = vp;
1321 }
1322 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001323 if (NULL == bound || !bound->isEmpty()) {
1324 rt->flagAsNeedingResolve(bound);
1325 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001326}
1327
twiz@google.com0f31ca72011-03-18 17:38:11 +00001328GrGLenum gPrimitiveType2GLMode[] = {
1329 GR_GL_TRIANGLES,
1330 GR_GL_TRIANGLE_STRIP,
1331 GR_GL_TRIANGLE_FAN,
1332 GR_GL_POINTS,
1333 GR_GL_LINES,
1334 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001335};
1336
bsalomon@google.comd302f142011-03-03 13:54:13 +00001337#define SWAP_PER_DRAW 0
1338
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001339#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001340 #if GR_MAC_BUILD
1341 #include <AGL/agl.h>
1342 #elif GR_WIN32_BUILD
1343 void SwapBuf() {
1344 DWORD procID = GetCurrentProcessId();
1345 HWND hwnd = GetTopWindow(GetDesktopWindow());
1346 while(hwnd) {
1347 DWORD wndProcID = 0;
1348 GetWindowThreadProcessId(hwnd, &wndProcID);
1349 if(wndProcID == procID) {
1350 SwapBuffers(GetDC(hwnd));
1351 }
1352 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1353 }
1354 }
1355 #endif
1356#endif
1357
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001358void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1359 uint32_t startVertex,
1360 uint32_t startIndex,
1361 uint32_t vertexCount,
1362 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001363 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1364
twiz@google.com0f31ca72011-03-18 17:38:11 +00001365 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001366
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001367 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1368 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1369
1370 // our setupGeometry better have adjusted this to zero since
1371 // DrawElements always draws from the begining of the arrays for idx 0.
1372 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001373
1374 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001375 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001376#if SWAP_PER_DRAW
1377 glFlush();
1378 #if GR_MAC_BUILD
1379 aglSwapBuffers(aglGetCurrentContext());
1380 int set_a_break_pt_here = 9;
1381 aglSwapBuffers(aglGetCurrentContext());
1382 #elif GR_WIN32_BUILD
1383 SwapBuf();
1384 int set_a_break_pt_here = 9;
1385 SwapBuf();
1386 #endif
1387#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001388}
1389
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001390void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1391 uint32_t startVertex,
1392 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001393 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1394
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001395 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1396
1397 // our setupGeometry better have adjusted this to zero.
1398 // DrawElements doesn't take an offset so we always adjus the startVertex.
1399 GrAssert(0 == startVertex);
1400
1401 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1402 // account for startVertex in the DrawElements case. So we always
1403 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001404 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001405#if SWAP_PER_DRAW
1406 glFlush();
1407 #if GR_MAC_BUILD
1408 aglSwapBuffers(aglGetCurrentContext());
1409 int set_a_break_pt_here = 9;
1410 aglSwapBuffers(aglGetCurrentContext());
1411 #elif GR_WIN32_BUILD
1412 SwapBuf();
1413 int set_a_break_pt_here = 9;
1414 SwapBuf();
1415 #endif
1416#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001417}
1418
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001419void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001420
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001421 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001422 GrAssert(kNone_MSFBO != fMSFBOType);
1423 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001424 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001425 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001426 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001427 rt->textureFBOID()));
1428 #if GR_COLLECT_STATS
1429 ++fStats.fRenderTargetChngCnt;
1430 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001431 // make sure we go through flushRenderTarget() since we've modified
1432 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001433 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001434 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001435 const GrIRect dirtyRect = rt->getResolveRect();
1436 GrGLIRect r;
1437 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1438 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001439
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001440 if (kAppleES_MSFBO == fMSFBOType) {
1441 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001442 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001443 GR_GL(Scissor(r.fLeft, r.fBottom,
1444 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001445 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001446 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001447 fHWBounds.fScissorEnabled = true;
1448 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001449 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001450 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001451 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1452 flushScissor(NULL);
1453 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001454 int right = r.fLeft + r.fWidth;
1455 int top = r.fBottom + r.fHeight;
1456 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1457 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001458 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001459 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001460 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001461 }
1462}
1463
twiz@google.com0f31ca72011-03-18 17:38:11 +00001464static const GrGLenum grToGLStencilFunc[] = {
1465 GR_GL_ALWAYS, // kAlways_StencilFunc
1466 GR_GL_NEVER, // kNever_StencilFunc
1467 GR_GL_GREATER, // kGreater_StencilFunc
1468 GR_GL_GEQUAL, // kGEqual_StencilFunc
1469 GR_GL_LESS, // kLess_StencilFunc
1470 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1471 GR_GL_EQUAL, // kEqual_StencilFunc,
1472 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001473};
1474GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1475GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1476GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1477GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1478GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1479GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1480GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1481GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1482GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1483
twiz@google.com0f31ca72011-03-18 17:38:11 +00001484static const GrGLenum grToGLStencilOp[] = {
1485 GR_GL_KEEP, // kKeep_StencilOp
1486 GR_GL_REPLACE, // kReplace_StencilOp
1487 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1488 GR_GL_INCR, // kIncClamp_StencilOp
1489 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1490 GR_GL_DECR, // kDecClamp_StencilOp
1491 GR_GL_ZERO, // kZero_StencilOp
1492 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001493};
1494GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1495GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1496GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1497GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1498GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1499GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1500GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1501GR_STATIC_ASSERT(6 == kZero_StencilOp);
1502GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1503
reed@google.comac10a2d2010-12-22 21:39:39 +00001504void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001505 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001506
1507 // use stencil for clipping if clipping is enabled and the clip
1508 // has been written into the stencil.
1509 bool stencilClip = fClipState.fClipInStencil &&
1510 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001511 bool stencilChange = fHWStencilClip != stencilClip ||
1512 fHWDrawState.fStencilSettings != *settings ||
1513 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1514 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001515
1516 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001517
bsalomon@google.comd302f142011-03-03 13:54:13 +00001518 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1519 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001520
bsalomon@google.comd302f142011-03-03 13:54:13 +00001521 if (settings->isDisabled()) {
1522 if (stencilClip) {
1523 settings = &gClipStencilSettings;
1524 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001525 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001526
1527 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001528 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001529 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001530 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001531 #if GR_DEBUG
1532 if (!fStencilWrapOpsSupport) {
1533 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1534 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1535 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1536 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1537 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1538 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1539 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1540 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1541 }
1542 #endif
1543 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1544 GrAssert(stencilBits ||
1545 (GrStencilSettings::gDisabled ==
1546 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001547 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1548 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001549
1550 unsigned int frontRef = settings->fFrontFuncRef;
1551 unsigned int frontMask = settings->fFrontFuncMask;
1552 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001553 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001554
1555 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1556
1557 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1558 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1559 } else {
1560 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1561
1562 ConvertStencilFuncAndMask(settings->fFrontFunc,
1563 stencilClip,
1564 clipStencilMask,
1565 userStencilMask,
1566 &frontRef,
1567 &frontMask);
1568 frontWriteMask &= userStencilMask;
1569 }
1570 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001571 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001572 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001573 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001574 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001575 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001576 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001577 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001578 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001579 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001580
1581 unsigned int backRef = settings->fBackFuncRef;
1582 unsigned int backMask = settings->fBackFuncMask;
1583 unsigned int backWriteMask = settings->fBackWriteMask;
1584
1585
1586 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1587 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1588 backFunc = grToGLStencilFunc[settings->fBackFunc];
1589 } else {
1590 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1591 ConvertStencilFuncAndMask(settings->fBackFunc,
1592 stencilClip,
1593 clipStencilMask,
1594 userStencilMask,
1595 &backRef,
1596 &backMask);
1597 backWriteMask &= userStencilMask;
1598 }
1599
twiz@google.com0f31ca72011-03-18 17:38:11 +00001600 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1601 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1602 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1603 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1604 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001605 grToGLStencilOp[settings->fFrontPassOp],
1606 grToGLStencilOp[settings->fFrontPassOp]));
1607
twiz@google.com0f31ca72011-03-18 17:38:11 +00001608 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001609 grToGLStencilOp[settings->fBackPassOp],
1610 grToGLStencilOp[settings->fBackPassOp]));
1611 } else {
1612 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1613 GR_GL(StencilMask(frontWriteMask));
1614 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1615 grToGLStencilOp[settings->fFrontPassOp],
1616 grToGLStencilOp[settings->fFrontPassOp]));
1617 }
1618 }
1619 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001620 fHWStencilClip = stencilClip;
1621 }
1622}
1623
bsalomon@google.com0650e812011-04-08 18:07:53 +00001624bool GrGpuGL::useSmoothLines() {
1625 // there is a conflict between using smooth lines and our use of
1626 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1627 // but not in a premul-alpha way. So we only use them when our alpha
1628 // is 0xff.
1629
1630 // TODO: write a smarter line frag shader.
1631
1632 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1633 canDisableBlend();
1634}
1635
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001636void GrGpuGL::flushAAState(GrPrimitiveType type) {
1637 if (GR_GL_SUPPORT_DESKTOP) {
1638 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1639 // smooth lines.
1640
1641 // we prefer smooth lines over multisampled lines
1642 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001643 if (GrIsPrimTypeLines(type)) {
1644 bool smooth = useSmoothLines();
1645 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001646 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1647 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001648 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001649 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1650 fHWAAState.fSmoothLineEnabled = false;
1651 }
1652 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1653 fHWAAState.fMSAAEnabled) {
1654 GR_GL(Disable(GR_GL_MULTISAMPLE));
1655 fHWAAState.fMSAAEnabled = false;
1656 }
1657 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1658 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1659 fHWAAState.fMSAAEnabled) {
1660 if (fHWAAState.fMSAAEnabled) {
1661 GR_GL(Disable(GR_GL_MULTISAMPLE));
1662 fHWAAState.fMSAAEnabled = false;
1663 } else {
1664 GR_GL(Enable(GR_GL_MULTISAMPLE));
1665 fHWAAState.fMSAAEnabled = true;
1666 }
1667 }
1668 }
1669}
1670
bsalomon@google.com0650e812011-04-08 18:07:53 +00001671void GrGpuGL::flushBlend(GrPrimitiveType type) {
1672 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1673 if (fHWBlendDisabled) {
1674 GR_GL(Enable(GR_GL_BLEND));
1675 fHWBlendDisabled = false;
1676 }
1677 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1678 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1679 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1680 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1681 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1682 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1683 }
1684 } else {
1685 bool blendOff = canDisableBlend();
1686 if (fHWBlendDisabled != blendOff) {
1687 if (blendOff) {
1688 GR_GL(Disable(GR_GL_BLEND));
1689 } else {
1690 GR_GL(Enable(GR_GL_BLEND));
1691 }
1692 fHWBlendDisabled = blendOff;
1693 }
1694 if (!blendOff) {
1695 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1696 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1697 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1698 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1699 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1700 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1701 }
1702 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1703 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1704 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1705
1706 float c[] = {
1707 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1708 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1709 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1710 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1711 };
1712 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1713 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1714 }
1715 }
1716 }
1717}
1718
bsalomon@google.comffca4002011-02-22 20:34:01 +00001719bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001720
1721 // GrGpu::setupClipAndFlushState should have already checked this
1722 // and bailed if not true.
1723 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001724
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001725 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001726 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001727 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001728 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001729
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001730 // true for now, but maybe not with GrEffect.
1731 GrAssert(NULL != nextTexture);
1732 // if we created a rt/tex and rendered to it without using a
1733 // texture and now we're texuring from the rt it will still be
1734 // the last bound texture, but it needs resolving. So keep this
1735 // out of the "last != next" check.
1736 GrGLRenderTarget* texRT =
1737 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1738 if (NULL != texRT) {
1739 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001740 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001741
1742 if (fHWDrawState.fTextures[s] != nextTexture) {
1743 setTextureUnit(s);
1744 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1745 #if GR_COLLECT_STATS
1746 ++fStats.fTextureChngCnt;
1747 #endif
1748 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1749 fHWDrawState.fTextures[s] = nextTexture;
1750 }
1751
1752 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1753 const GrGLTexture::TexParams& oldTexParams =
1754 nextTexture->getTexParams();
1755 GrGLTexture::TexParams newTexParams;
1756
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001757 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1758 newTexParams.fFilter = GR_GL_NEAREST;
1759 } else {
1760 newTexParams.fFilter = GR_GL_LINEAR;
1761 }
1762
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001763 newTexParams.fWrapS =
1764 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1765 newTexParams.fWrapT =
1766 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1767
1768 if (newTexParams.fFilter != oldTexParams.fFilter) {
1769 setTextureUnit(s);
1770 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1771 GR_GL_TEXTURE_MAG_FILTER,
1772 newTexParams.fFilter));
1773 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1774 GR_GL_TEXTURE_MIN_FILTER,
1775 newTexParams.fFilter));
1776 }
1777 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1778 setTextureUnit(s);
1779 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1780 GR_GL_TEXTURE_WRAP_S,
1781 newTexParams.fWrapS));
1782 }
1783 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1784 setTextureUnit(s);
1785 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1786 GR_GL_TEXTURE_WRAP_T,
1787 newTexParams.fWrapT));
1788 }
1789 nextTexture->setTexParams(newTexParams);
1790
1791 // The texture matrix has to compensate for texture width/height
1792 // and NPOT-embedded-in-POT
1793 fDirtyFlags.fTextureChangedMask |= (1 << s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001794 }
1795 }
1796
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001797 GrIRect* rect = NULL;
1798 GrIRect clipBounds;
1799 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1800 fClip.hasConservativeBounds()) {
1801 fClip.getConservativeBounds().roundOut(&clipBounds);
1802 rect = &clipBounds;
1803 }
1804 this->flushRenderTarget(rect);
1805 this->flushAAState(type);
1806 this->flushBlend(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001807
reed@google.comac10a2d2010-12-22 21:39:39 +00001808 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1809 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1810 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001811 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001812 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001813 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001814 }
1815 }
1816
bsalomon@google.comd302f142011-03-03 13:54:13 +00001817 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1818 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001819 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001820 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001821 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001822 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001823 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001824 }
1825 GR_GL(ColorMask(mask, mask, mask, mask));
1826 }
1827
bsalomon@google.comd302f142011-03-03 13:54:13 +00001828 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1829 switch (fCurrDrawState.fDrawFace) {
1830 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001831 GR_GL(Enable(GR_GL_CULL_FACE));
1832 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001833 break;
1834 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001835 GR_GL(Enable(GR_GL_CULL_FACE));
1836 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001837 break;
1838 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001839 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001840 break;
1841 default:
1842 GrCrash("Unknown draw face.");
1843 }
1844 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1845 }
1846
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001847#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001848 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001849 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001850 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001851 NULL == fCurrDrawState.fRenderTarget ||
1852 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001853 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001854 fCurrDrawState.fRenderTarget);
1855 }
1856#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001857
reed@google.comac10a2d2010-12-22 21:39:39 +00001858 flushStencil();
1859
bsalomon@google.comd302f142011-03-03 13:54:13 +00001860 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001861 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001862 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001863}
1864
1865void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001866 if (fHWGeometryState.fVertexBuffer != buffer) {
1867 fHWGeometryState.fArrayPtrsDirty = true;
1868 fHWGeometryState.fVertexBuffer = buffer;
1869 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001870}
1871
1872void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001873 if (fHWGeometryState.fVertexBuffer == buffer) {
1874 // deleting bound buffer does implied bind to 0
1875 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001876 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001877 }
1878}
1879
1880void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1881 fGeometrySrc.fIndexBuffer = buffer;
1882}
1883
1884void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001885 if (fHWGeometryState.fIndexBuffer == buffer) {
1886 // deleting bound buffer does implied bind to 0
1887 fHWGeometryState.fIndexBuffer = NULL;
1888 }
1889}
1890
reed@google.comac10a2d2010-12-22 21:39:39 +00001891void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1892 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001893 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001894 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001895 }
1896 if (fHWDrawState.fRenderTarget == renderTarget) {
1897 fHWDrawState.fRenderTarget = NULL;
1898 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001899}
1900
1901void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001902 for (int s = 0; s < kNumStages; ++s) {
1903 if (fCurrDrawState.fTextures[s] == texture) {
1904 fCurrDrawState.fTextures[s] = NULL;
1905 }
1906 if (fHWDrawState.fTextures[s] == texture) {
1907 // deleting bound texture does implied bind to 0
1908 fHWDrawState.fTextures[s] = NULL;
1909 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001910 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001911}
1912
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001913bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001914 GrGLenum* internalFormat,
1915 GrGLenum* format,
1916 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001917 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001918 case kRGBA_8888_GrPixelConfig:
1919 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001920 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001921 if (GR_GL_SUPPORT_ES) {
1922 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1923 // format for a BGRA is BGRA not RGBA (as on desktop)
1924 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1925 } else {
1926 *internalFormat = GR_GL_RGBA;
1927 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001928 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001929 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001930 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001931 *format = GR_GL_RGB;
1932 *internalFormat = GR_GL_RGB;
1933 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001934 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001935 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001936 *format = GR_GL_RGBA;
1937 *internalFormat = GR_GL_RGBA;
1938 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001939 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001940 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001941 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001942 *format = GR_GL_PALETTE8_RGBA8;
1943 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001944 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001945 } else {
1946 return false;
1947 }
1948 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001949 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001950 *format = GR_GL_ALPHA;
1951 *internalFormat = GR_GL_ALPHA;
1952 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001953 break;
1954 default:
1955 return false;
1956 }
1957 return true;
1958}
1959
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001960void GrGpuGL::setTextureUnit(int unit) {
1961 GrAssert(unit >= 0 && unit < kNumStages);
1962 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001963 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001964 fActiveTextureUnitIdx = unit;
1965 }
1966}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001967
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001968void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001969 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1970 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001971 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1972 }
1973}
1974
reed@google.comac10a2d2010-12-22 21:39:39 +00001975/* On ES the internalFormat and format must match for TexImage and we use
1976 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1977 decide the internalFormat. However, on ES internalFormat for
1978 RenderBufferStorage* has to be a specific format (not a base format like
1979 GL_RGBA).
1980 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001981bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001982 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001983 case kRGBA_8888_GrPixelConfig:
1984 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001985 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001986 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001987 return true;
1988 } else {
1989 return false;
1990 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001991 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001992 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1993 // with FBO extension desktop GL has
1994 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001995 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001996 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001997 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001998 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001999 return true;
2000 default:
2001 return false;
2002 }
2003}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002004
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002005void GrGpuGL::resetDirtyFlags() {
2006 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2007}
2008
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002009void GrGpuGL::setBuffers(bool indexed,
2010 int* extraVertexOffset,
2011 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002012
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002013 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002014
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002015 GrGLVertexBuffer* vbuf;
2016 switch (fGeometrySrc.fVertexSrc) {
2017 case kBuffer_GeometrySrcType:
2018 *extraVertexOffset = 0;
2019 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2020 break;
2021 case kArray_GeometrySrcType:
2022 case kReserved_GeometrySrcType:
2023 finalizeReservedVertices();
2024 *extraVertexOffset = fCurrPoolStartVertex;
2025 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2026 break;
2027 default:
2028 vbuf = NULL; // suppress warning
2029 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002030 }
2031
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002032 GrAssert(NULL != vbuf);
2033 GrAssert(!vbuf->isLocked());
2034 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002035 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002036 fHWGeometryState.fArrayPtrsDirty = true;
2037 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002038 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002039
2040 if (indexed) {
2041 GrAssert(NULL != extraIndexOffset);
2042
2043 GrGLIndexBuffer* ibuf;
2044 switch (fGeometrySrc.fIndexSrc) {
2045 case kBuffer_GeometrySrcType:
2046 *extraIndexOffset = 0;
2047 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2048 break;
2049 case kArray_GeometrySrcType:
2050 case kReserved_GeometrySrcType:
2051 finalizeReservedIndices();
2052 *extraIndexOffset = fCurrPoolStartIndex;
2053 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2054 break;
2055 default:
2056 ibuf = NULL; // suppress warning
2057 GrCrash("Unknown geometry src type!");
2058 }
2059
2060 GrAssert(NULL != ibuf);
2061 GrAssert(!ibuf->isLocked());
2062 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002063 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002064 fHWGeometryState.fIndexBuffer = ibuf;
2065 }
2066 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002067}