blob: 721d084d12920ec595d1e6d8468f1c17bf6c6582 [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
1757 newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR :
1758 GR_GL_NEAREST;
1759 newTexParams.fWrapS =
1760 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1761 newTexParams.fWrapT =
1762 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1763
1764 if (newTexParams.fFilter != oldTexParams.fFilter) {
1765 setTextureUnit(s);
1766 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1767 GR_GL_TEXTURE_MAG_FILTER,
1768 newTexParams.fFilter));
1769 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1770 GR_GL_TEXTURE_MIN_FILTER,
1771 newTexParams.fFilter));
1772 }
1773 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1774 setTextureUnit(s);
1775 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1776 GR_GL_TEXTURE_WRAP_S,
1777 newTexParams.fWrapS));
1778 }
1779 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1780 setTextureUnit(s);
1781 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1782 GR_GL_TEXTURE_WRAP_T,
1783 newTexParams.fWrapT));
1784 }
1785 nextTexture->setTexParams(newTexParams);
1786
1787 // The texture matrix has to compensate for texture width/height
1788 // and NPOT-embedded-in-POT
1789 fDirtyFlags.fTextureChangedMask |= (1 << s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001790 }
1791 }
1792
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001793 GrIRect* rect = NULL;
1794 GrIRect clipBounds;
1795 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1796 fClip.hasConservativeBounds()) {
1797 fClip.getConservativeBounds().roundOut(&clipBounds);
1798 rect = &clipBounds;
1799 }
1800 this->flushRenderTarget(rect);
1801 this->flushAAState(type);
1802 this->flushBlend(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001803
reed@google.comac10a2d2010-12-22 21:39:39 +00001804 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1805 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1806 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001807 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001808 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001809 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001810 }
1811 }
1812
bsalomon@google.comd302f142011-03-03 13:54:13 +00001813 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1814 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001815 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001816 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001817 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001818 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001819 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001820 }
1821 GR_GL(ColorMask(mask, mask, mask, mask));
1822 }
1823
bsalomon@google.comd302f142011-03-03 13:54:13 +00001824 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1825 switch (fCurrDrawState.fDrawFace) {
1826 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001827 GR_GL(Enable(GR_GL_CULL_FACE));
1828 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001829 break;
1830 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001831 GR_GL(Enable(GR_GL_CULL_FACE));
1832 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001833 break;
1834 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001835 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001836 break;
1837 default:
1838 GrCrash("Unknown draw face.");
1839 }
1840 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1841 }
1842
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001843#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001844 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001845 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001846 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001847 NULL == fCurrDrawState.fRenderTarget ||
1848 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001849 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001850 fCurrDrawState.fRenderTarget);
1851 }
1852#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001853
reed@google.comac10a2d2010-12-22 21:39:39 +00001854 flushStencil();
1855
bsalomon@google.comd302f142011-03-03 13:54:13 +00001856 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001857 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001858 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001859}
1860
1861void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001862 if (fHWGeometryState.fVertexBuffer != buffer) {
1863 fHWGeometryState.fArrayPtrsDirty = true;
1864 fHWGeometryState.fVertexBuffer = buffer;
1865 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001866}
1867
1868void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001869 if (fHWGeometryState.fVertexBuffer == buffer) {
1870 // deleting bound buffer does implied bind to 0
1871 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001872 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001873 }
1874}
1875
1876void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1877 fGeometrySrc.fIndexBuffer = buffer;
1878}
1879
1880void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001881 if (fHWGeometryState.fIndexBuffer == buffer) {
1882 // deleting bound buffer does implied bind to 0
1883 fHWGeometryState.fIndexBuffer = NULL;
1884 }
1885}
1886
reed@google.comac10a2d2010-12-22 21:39:39 +00001887void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1888 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001889 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001890 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001891 }
1892 if (fHWDrawState.fRenderTarget == renderTarget) {
1893 fHWDrawState.fRenderTarget = NULL;
1894 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001895}
1896
1897void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001898 for (int s = 0; s < kNumStages; ++s) {
1899 if (fCurrDrawState.fTextures[s] == texture) {
1900 fCurrDrawState.fTextures[s] = NULL;
1901 }
1902 if (fHWDrawState.fTextures[s] == texture) {
1903 // deleting bound texture does implied bind to 0
1904 fHWDrawState.fTextures[s] = NULL;
1905 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001906 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001907}
1908
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001909bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001910 GrGLenum* internalFormat,
1911 GrGLenum* format,
1912 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001913 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001914 case kRGBA_8888_GrPixelConfig:
1915 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001916 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001917 if (GR_GL_SUPPORT_ES) {
1918 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1919 // format for a BGRA is BGRA not RGBA (as on desktop)
1920 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1921 } else {
1922 *internalFormat = GR_GL_RGBA;
1923 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001924 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001925 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001926 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001927 *format = GR_GL_RGB;
1928 *internalFormat = GR_GL_RGB;
1929 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001930 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001931 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001932 *format = GR_GL_RGBA;
1933 *internalFormat = GR_GL_RGBA;
1934 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001935 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001936 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001937 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001938 *format = GR_GL_PALETTE8_RGBA8;
1939 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001940 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001941 } else {
1942 return false;
1943 }
1944 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001945 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001946 *format = GR_GL_ALPHA;
1947 *internalFormat = GR_GL_ALPHA;
1948 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001949 break;
1950 default:
1951 return false;
1952 }
1953 return true;
1954}
1955
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001956void GrGpuGL::setTextureUnit(int unit) {
1957 GrAssert(unit >= 0 && unit < kNumStages);
1958 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001959 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001960 fActiveTextureUnitIdx = unit;
1961 }
1962}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001963
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001964void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001965 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1966 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001967 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1968 }
1969}
1970
reed@google.comac10a2d2010-12-22 21:39:39 +00001971/* On ES the internalFormat and format must match for TexImage and we use
1972 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1973 decide the internalFormat. However, on ES internalFormat for
1974 RenderBufferStorage* has to be a specific format (not a base format like
1975 GL_RGBA).
1976 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001977bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001978 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001979 case kRGBA_8888_GrPixelConfig:
1980 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001981 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001982 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001983 return true;
1984 } else {
1985 return false;
1986 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001987 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001988 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1989 // with FBO extension desktop GL has
1990 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001991 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001992 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001993 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001994 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001995 return true;
1996 default:
1997 return false;
1998 }
1999}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002000
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002001void GrGpuGL::resetDirtyFlags() {
2002 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2003}
2004
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002005void GrGpuGL::setBuffers(bool indexed,
2006 int* extraVertexOffset,
2007 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002008
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002009 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002010
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002011 GrGLVertexBuffer* vbuf;
2012 switch (fGeometrySrc.fVertexSrc) {
2013 case kBuffer_GeometrySrcType:
2014 *extraVertexOffset = 0;
2015 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2016 break;
2017 case kArray_GeometrySrcType:
2018 case kReserved_GeometrySrcType:
2019 finalizeReservedVertices();
2020 *extraVertexOffset = fCurrPoolStartVertex;
2021 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2022 break;
2023 default:
2024 vbuf = NULL; // suppress warning
2025 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002026 }
2027
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002028 GrAssert(NULL != vbuf);
2029 GrAssert(!vbuf->isLocked());
2030 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002031 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002032 fHWGeometryState.fArrayPtrsDirty = true;
2033 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002034 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002035
2036 if (indexed) {
2037 GrAssert(NULL != extraIndexOffset);
2038
2039 GrGLIndexBuffer* ibuf;
2040 switch (fGeometrySrc.fIndexSrc) {
2041 case kBuffer_GeometrySrcType:
2042 *extraIndexOffset = 0;
2043 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2044 break;
2045 case kArray_GeometrySrcType:
2046 case kReserved_GeometrySrcType:
2047 finalizeReservedIndices();
2048 *extraIndexOffset = fCurrPoolStartIndex;
2049 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2050 break;
2051 default:
2052 ibuf = NULL; // suppress warning
2053 GrCrash("Unknown geometry src type!");
2054 }
2055
2056 GrAssert(NULL != ibuf);
2057 GrAssert(!ibuf->isLocked());
2058 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002059 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002060 fHWGeometryState.fIndexBuffer = ibuf;
2061 }
2062 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002063}