blob: e8c7afb0edd3fefaa1cd4711900aa32393fa49cb [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;
reed@google.com20efde72011-05-09 17:00:02 +00001178 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1179 fCurrDrawState.fRenderTarget->height());
1180 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001181 rect = &r;
1182 } else {
1183 return;
1184 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001185 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001186 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001187 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001188 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001189 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001190 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1191 GrColorUnpackG(color)/255.f,
1192 GrColorUnpackB(color)/255.f,
1193 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001194 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001195}
1196
bsalomon@google.com398109c2011-04-14 18:40:27 +00001197void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001198 if (NULL == fCurrDrawState.fRenderTarget) {
1199 return;
1200 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001201
1202 this->flushRenderTarget(&GrIRect::EmptyIRect());
1203
reed@google.comac10a2d2010-12-22 21:39:39 +00001204 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001205 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001206 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001207 }
1208 GR_GL(StencilMask(mask));
1209 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001210 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001211 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001212}
1213
bsalomon@google.com398109c2011-04-14 18:40:27 +00001214void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001215 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001216#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001217 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001218 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001219 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001220#else
1221 // we could just clear the clip bit but when we go through
1222 // angle a partial stencil mask will cause clears to be
1223 // turned into draws. Our contract on GrDrawTarget says that
1224 // changing the clip between stencil passes may or may not
1225 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001226 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001227#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001228 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001229 flushScissor(&rect);
1230 GR_GL(StencilMask(clipStencilMask));
1231 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001232 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001233 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001234}
1235
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001236void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001237 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001238}
1239
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001240bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1241 int left, int top, int width, int height,
1242 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001243 GrGLenum internalFormat; // we don't use this for glReadPixels
1244 GrGLenum format;
1245 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001246 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1247 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001248 }
1249 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1250 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1251 switch (tgt->getResolveType()) {
1252 case GrGLRenderTarget::kCantResolve_ResolveType:
1253 return false;
1254 case GrGLRenderTarget::kAutoResolves_ResolveType:
1255 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1256 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001257 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001258 break;
1259 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001260 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001261 // we don't track the state of the READ FBO ID.
1262 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1263 break;
1264 default:
1265 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001266 }
1267
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001268 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001269
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001270 // the read rect is viewport-relative
1271 GrGLIRect readRect;
1272 readRect.setRelativeTo(glvp, left, top, width, height);
1273 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001274 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001275 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001276
1277 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1278 // API presents top-to-bottom
1279 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001280 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001281 GrAutoMalloc rowStorage(stride);
1282 void* tmp = rowStorage.get();
1283
1284 const int halfY = height >> 1;
1285 char* top = reinterpret_cast<char*>(buffer);
1286 char* bottom = top + (height - 1) * stride;
1287 for (int y = 0; y < halfY; y++) {
1288 memcpy(tmp, top, stride);
1289 memcpy(top, bottom, stride);
1290 memcpy(bottom, tmp, stride);
1291 top += stride;
1292 bottom -= stride;
1293 }
1294 }
1295 return true;
1296}
1297
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001298void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001299
1300 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1301
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001302 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001303 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001304 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001305 #if GR_COLLECT_STATS
1306 ++fStats.fRenderTargetChngCnt;
1307 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001308 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001309 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1310 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001311 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1312 }
1313 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001314 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001315 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001316 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001317 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001318 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001319 fHWBounds.fViewportRect = vp;
1320 }
1321 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001322 if (NULL == bound || !bound->isEmpty()) {
1323 rt->flagAsNeedingResolve(bound);
1324 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001325}
1326
twiz@google.com0f31ca72011-03-18 17:38:11 +00001327GrGLenum gPrimitiveType2GLMode[] = {
1328 GR_GL_TRIANGLES,
1329 GR_GL_TRIANGLE_STRIP,
1330 GR_GL_TRIANGLE_FAN,
1331 GR_GL_POINTS,
1332 GR_GL_LINES,
1333 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001334};
1335
bsalomon@google.comd302f142011-03-03 13:54:13 +00001336#define SWAP_PER_DRAW 0
1337
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001338#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001339 #if GR_MAC_BUILD
1340 #include <AGL/agl.h>
1341 #elif GR_WIN32_BUILD
1342 void SwapBuf() {
1343 DWORD procID = GetCurrentProcessId();
1344 HWND hwnd = GetTopWindow(GetDesktopWindow());
1345 while(hwnd) {
1346 DWORD wndProcID = 0;
1347 GetWindowThreadProcessId(hwnd, &wndProcID);
1348 if(wndProcID == procID) {
1349 SwapBuffers(GetDC(hwnd));
1350 }
1351 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1352 }
1353 }
1354 #endif
1355#endif
1356
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001357void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1358 uint32_t startVertex,
1359 uint32_t startIndex,
1360 uint32_t vertexCount,
1361 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001362 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1363
twiz@google.com0f31ca72011-03-18 17:38:11 +00001364 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001365
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001366 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1367 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1368
1369 // our setupGeometry better have adjusted this to zero since
1370 // DrawElements always draws from the begining of the arrays for idx 0.
1371 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001372
1373 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001374 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001375#if SWAP_PER_DRAW
1376 glFlush();
1377 #if GR_MAC_BUILD
1378 aglSwapBuffers(aglGetCurrentContext());
1379 int set_a_break_pt_here = 9;
1380 aglSwapBuffers(aglGetCurrentContext());
1381 #elif GR_WIN32_BUILD
1382 SwapBuf();
1383 int set_a_break_pt_here = 9;
1384 SwapBuf();
1385 #endif
1386#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001387}
1388
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001389void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1390 uint32_t startVertex,
1391 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001392 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1393
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001394 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1395
1396 // our setupGeometry better have adjusted this to zero.
1397 // DrawElements doesn't take an offset so we always adjus the startVertex.
1398 GrAssert(0 == startVertex);
1399
1400 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1401 // account for startVertex in the DrawElements case. So we always
1402 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001403 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001404#if SWAP_PER_DRAW
1405 glFlush();
1406 #if GR_MAC_BUILD
1407 aglSwapBuffers(aglGetCurrentContext());
1408 int set_a_break_pt_here = 9;
1409 aglSwapBuffers(aglGetCurrentContext());
1410 #elif GR_WIN32_BUILD
1411 SwapBuf();
1412 int set_a_break_pt_here = 9;
1413 SwapBuf();
1414 #endif
1415#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001416}
1417
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001418void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001419
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001420 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001421 GrAssert(kNone_MSFBO != fMSFBOType);
1422 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001423 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001424 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001425 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001426 rt->textureFBOID()));
1427 #if GR_COLLECT_STATS
1428 ++fStats.fRenderTargetChngCnt;
1429 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001430 // make sure we go through flushRenderTarget() since we've modified
1431 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001432 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001433 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001434 const GrIRect dirtyRect = rt->getResolveRect();
1435 GrGLIRect r;
1436 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1437 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001438
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001439 if (kAppleES_MSFBO == fMSFBOType) {
1440 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001441 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001442 GR_GL(Scissor(r.fLeft, r.fBottom,
1443 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001444 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001445 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001446 fHWBounds.fScissorEnabled = true;
1447 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001448 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001449 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001450 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1451 flushScissor(NULL);
1452 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001453 int right = r.fLeft + r.fWidth;
1454 int top = r.fBottom + r.fHeight;
1455 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1456 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001457 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001458 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001459 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001460 }
1461}
1462
twiz@google.com0f31ca72011-03-18 17:38:11 +00001463static const GrGLenum grToGLStencilFunc[] = {
1464 GR_GL_ALWAYS, // kAlways_StencilFunc
1465 GR_GL_NEVER, // kNever_StencilFunc
1466 GR_GL_GREATER, // kGreater_StencilFunc
1467 GR_GL_GEQUAL, // kGEqual_StencilFunc
1468 GR_GL_LESS, // kLess_StencilFunc
1469 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1470 GR_GL_EQUAL, // kEqual_StencilFunc,
1471 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001472};
1473GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1474GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1475GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1476GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1477GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1478GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1479GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1480GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1481GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1482
twiz@google.com0f31ca72011-03-18 17:38:11 +00001483static const GrGLenum grToGLStencilOp[] = {
1484 GR_GL_KEEP, // kKeep_StencilOp
1485 GR_GL_REPLACE, // kReplace_StencilOp
1486 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1487 GR_GL_INCR, // kIncClamp_StencilOp
1488 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1489 GR_GL_DECR, // kDecClamp_StencilOp
1490 GR_GL_ZERO, // kZero_StencilOp
1491 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001492};
1493GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1494GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1495GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1496GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1497GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1498GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1499GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1500GR_STATIC_ASSERT(6 == kZero_StencilOp);
1501GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1502
reed@google.comac10a2d2010-12-22 21:39:39 +00001503void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001504 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001505
1506 // use stencil for clipping if clipping is enabled and the clip
1507 // has been written into the stencil.
1508 bool stencilClip = fClipState.fClipInStencil &&
1509 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001510 bool stencilChange = fHWStencilClip != stencilClip ||
1511 fHWDrawState.fStencilSettings != *settings ||
1512 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1513 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001514
1515 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001516
bsalomon@google.comd302f142011-03-03 13:54:13 +00001517 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1518 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001519
bsalomon@google.comd302f142011-03-03 13:54:13 +00001520 if (settings->isDisabled()) {
1521 if (stencilClip) {
1522 settings = &gClipStencilSettings;
1523 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001524 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001525
1526 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001527 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001528 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001529 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001530 #if GR_DEBUG
1531 if (!fStencilWrapOpsSupport) {
1532 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1533 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1534 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1535 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1536 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1537 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1538 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1539 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1540 }
1541 #endif
1542 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1543 GrAssert(stencilBits ||
1544 (GrStencilSettings::gDisabled ==
1545 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001546 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1547 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001548
1549 unsigned int frontRef = settings->fFrontFuncRef;
1550 unsigned int frontMask = settings->fFrontFuncMask;
1551 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001552 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001553
1554 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1555
1556 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1557 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1558 } else {
1559 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1560
1561 ConvertStencilFuncAndMask(settings->fFrontFunc,
1562 stencilClip,
1563 clipStencilMask,
1564 userStencilMask,
1565 &frontRef,
1566 &frontMask);
1567 frontWriteMask &= userStencilMask;
1568 }
1569 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001570 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001571 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001572 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001573 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001574 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001575 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001576 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001577 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001578 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001579
1580 unsigned int backRef = settings->fBackFuncRef;
1581 unsigned int backMask = settings->fBackFuncMask;
1582 unsigned int backWriteMask = settings->fBackWriteMask;
1583
1584
1585 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1586 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1587 backFunc = grToGLStencilFunc[settings->fBackFunc];
1588 } else {
1589 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1590 ConvertStencilFuncAndMask(settings->fBackFunc,
1591 stencilClip,
1592 clipStencilMask,
1593 userStencilMask,
1594 &backRef,
1595 &backMask);
1596 backWriteMask &= userStencilMask;
1597 }
1598
twiz@google.com0f31ca72011-03-18 17:38:11 +00001599 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1600 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1601 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1602 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1603 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001604 grToGLStencilOp[settings->fFrontPassOp],
1605 grToGLStencilOp[settings->fFrontPassOp]));
1606
twiz@google.com0f31ca72011-03-18 17:38:11 +00001607 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001608 grToGLStencilOp[settings->fBackPassOp],
1609 grToGLStencilOp[settings->fBackPassOp]));
1610 } else {
1611 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1612 GR_GL(StencilMask(frontWriteMask));
1613 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1614 grToGLStencilOp[settings->fFrontPassOp],
1615 grToGLStencilOp[settings->fFrontPassOp]));
1616 }
1617 }
1618 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001619 fHWStencilClip = stencilClip;
1620 }
1621}
1622
bsalomon@google.com0650e812011-04-08 18:07:53 +00001623bool GrGpuGL::useSmoothLines() {
1624 // there is a conflict between using smooth lines and our use of
1625 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1626 // but not in a premul-alpha way. So we only use them when our alpha
1627 // is 0xff.
1628
1629 // TODO: write a smarter line frag shader.
1630
1631 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1632 canDisableBlend();
1633}
1634
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001635void GrGpuGL::flushAAState(GrPrimitiveType type) {
1636 if (GR_GL_SUPPORT_DESKTOP) {
1637 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1638 // smooth lines.
1639
1640 // we prefer smooth lines over multisampled lines
1641 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001642 if (GrIsPrimTypeLines(type)) {
1643 bool smooth = useSmoothLines();
1644 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001645 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1646 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001647 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001648 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1649 fHWAAState.fSmoothLineEnabled = false;
1650 }
1651 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1652 fHWAAState.fMSAAEnabled) {
1653 GR_GL(Disable(GR_GL_MULTISAMPLE));
1654 fHWAAState.fMSAAEnabled = false;
1655 }
1656 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1657 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1658 fHWAAState.fMSAAEnabled) {
1659 if (fHWAAState.fMSAAEnabled) {
1660 GR_GL(Disable(GR_GL_MULTISAMPLE));
1661 fHWAAState.fMSAAEnabled = false;
1662 } else {
1663 GR_GL(Enable(GR_GL_MULTISAMPLE));
1664 fHWAAState.fMSAAEnabled = true;
1665 }
1666 }
1667 }
1668}
1669
bsalomon@google.com0650e812011-04-08 18:07:53 +00001670void GrGpuGL::flushBlend(GrPrimitiveType type) {
1671 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1672 if (fHWBlendDisabled) {
1673 GR_GL(Enable(GR_GL_BLEND));
1674 fHWBlendDisabled = false;
1675 }
1676 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1677 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1678 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1679 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1680 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1681 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1682 }
1683 } else {
1684 bool blendOff = canDisableBlend();
1685 if (fHWBlendDisabled != blendOff) {
1686 if (blendOff) {
1687 GR_GL(Disable(GR_GL_BLEND));
1688 } else {
1689 GR_GL(Enable(GR_GL_BLEND));
1690 }
1691 fHWBlendDisabled = blendOff;
1692 }
1693 if (!blendOff) {
1694 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1695 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1696 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1697 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1698 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1699 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1700 }
1701 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1702 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1703 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1704
1705 float c[] = {
1706 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1707 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1708 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1709 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1710 };
1711 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1712 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1713 }
1714 }
1715 }
1716}
1717
bsalomon@google.comffca4002011-02-22 20:34:01 +00001718bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001719
1720 // GrGpu::setupClipAndFlushState should have already checked this
1721 // and bailed if not true.
1722 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001723
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001724 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001725 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001726 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001727 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001728
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001729 // true for now, but maybe not with GrEffect.
1730 GrAssert(NULL != nextTexture);
1731 // if we created a rt/tex and rendered to it without using a
1732 // texture and now we're texuring from the rt it will still be
1733 // the last bound texture, but it needs resolving. So keep this
1734 // out of the "last != next" check.
1735 GrGLRenderTarget* texRT =
1736 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1737 if (NULL != texRT) {
1738 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001739 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001740
1741 if (fHWDrawState.fTextures[s] != nextTexture) {
1742 setTextureUnit(s);
1743 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1744 #if GR_COLLECT_STATS
1745 ++fStats.fTextureChngCnt;
1746 #endif
1747 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1748 fHWDrawState.fTextures[s] = nextTexture;
1749 }
1750
1751 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1752 const GrGLTexture::TexParams& oldTexParams =
1753 nextTexture->getTexParams();
1754 GrGLTexture::TexParams newTexParams;
1755
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001756 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1757 newTexParams.fFilter = GR_GL_NEAREST;
1758 } else {
1759 newTexParams.fFilter = GR_GL_LINEAR;
1760 }
1761
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001762 newTexParams.fWrapS =
1763 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1764 newTexParams.fWrapT =
1765 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1766
1767 if (newTexParams.fFilter != oldTexParams.fFilter) {
1768 setTextureUnit(s);
1769 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1770 GR_GL_TEXTURE_MAG_FILTER,
1771 newTexParams.fFilter));
1772 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1773 GR_GL_TEXTURE_MIN_FILTER,
1774 newTexParams.fFilter));
1775 }
1776 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1777 setTextureUnit(s);
1778 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1779 GR_GL_TEXTURE_WRAP_S,
1780 newTexParams.fWrapS));
1781 }
1782 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1783 setTextureUnit(s);
1784 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1785 GR_GL_TEXTURE_WRAP_T,
1786 newTexParams.fWrapT));
1787 }
1788 nextTexture->setTexParams(newTexParams);
1789
1790 // The texture matrix has to compensate for texture width/height
1791 // and NPOT-embedded-in-POT
1792 fDirtyFlags.fTextureChangedMask |= (1 << s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001793 }
1794 }
1795
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001796 GrIRect* rect = NULL;
1797 GrIRect clipBounds;
1798 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1799 fClip.hasConservativeBounds()) {
1800 fClip.getConservativeBounds().roundOut(&clipBounds);
1801 rect = &clipBounds;
1802 }
1803 this->flushRenderTarget(rect);
1804 this->flushAAState(type);
1805 this->flushBlend(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001806
reed@google.comac10a2d2010-12-22 21:39:39 +00001807 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1808 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1809 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001810 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001811 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001812 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001813 }
1814 }
1815
bsalomon@google.comd302f142011-03-03 13:54:13 +00001816 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1817 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001818 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001819 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001820 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001821 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001822 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001823 }
1824 GR_GL(ColorMask(mask, mask, mask, mask));
1825 }
1826
bsalomon@google.comd302f142011-03-03 13:54:13 +00001827 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1828 switch (fCurrDrawState.fDrawFace) {
1829 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001830 GR_GL(Enable(GR_GL_CULL_FACE));
1831 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001832 break;
1833 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001834 GR_GL(Enable(GR_GL_CULL_FACE));
1835 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001836 break;
1837 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001838 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001839 break;
1840 default:
1841 GrCrash("Unknown draw face.");
1842 }
1843 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1844 }
1845
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001846#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001847 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001848 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001849 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001850 NULL == fCurrDrawState.fRenderTarget ||
1851 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001852 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001853 fCurrDrawState.fRenderTarget);
1854 }
1855#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001856
reed@google.comac10a2d2010-12-22 21:39:39 +00001857 flushStencil();
1858
bsalomon@google.comd302f142011-03-03 13:54:13 +00001859 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001860 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001861 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001862}
1863
1864void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001865 if (fHWGeometryState.fVertexBuffer != buffer) {
1866 fHWGeometryState.fArrayPtrsDirty = true;
1867 fHWGeometryState.fVertexBuffer = buffer;
1868 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001869}
1870
1871void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001872 if (fHWGeometryState.fVertexBuffer == buffer) {
1873 // deleting bound buffer does implied bind to 0
1874 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001875 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001876 }
1877}
1878
1879void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1880 fGeometrySrc.fIndexBuffer = buffer;
1881}
1882
1883void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001884 if (fHWGeometryState.fIndexBuffer == buffer) {
1885 // deleting bound buffer does implied bind to 0
1886 fHWGeometryState.fIndexBuffer = NULL;
1887 }
1888}
1889
reed@google.comac10a2d2010-12-22 21:39:39 +00001890void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1891 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001892 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001893 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001894 }
1895 if (fHWDrawState.fRenderTarget == renderTarget) {
1896 fHWDrawState.fRenderTarget = NULL;
1897 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001898}
1899
1900void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001901 for (int s = 0; s < kNumStages; ++s) {
1902 if (fCurrDrawState.fTextures[s] == texture) {
1903 fCurrDrawState.fTextures[s] = NULL;
1904 }
1905 if (fHWDrawState.fTextures[s] == texture) {
1906 // deleting bound texture does implied bind to 0
1907 fHWDrawState.fTextures[s] = NULL;
1908 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001909 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001910}
1911
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001912bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001913 GrGLenum* internalFormat,
1914 GrGLenum* format,
1915 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001916 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001917 case kRGBA_8888_GrPixelConfig:
1918 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001919 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001920 if (GR_GL_SUPPORT_ES) {
1921 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1922 // format for a BGRA is BGRA not RGBA (as on desktop)
1923 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1924 } else {
1925 *internalFormat = GR_GL_RGBA;
1926 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001927 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001928 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001929 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001930 *format = GR_GL_RGB;
1931 *internalFormat = GR_GL_RGB;
1932 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001933 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001934 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001935 *format = GR_GL_RGBA;
1936 *internalFormat = GR_GL_RGBA;
1937 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001938 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001939 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001940 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001941 *format = GR_GL_PALETTE8_RGBA8;
1942 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001943 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001944 } else {
1945 return false;
1946 }
1947 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001948 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001949 *format = GR_GL_ALPHA;
1950 *internalFormat = GR_GL_ALPHA;
1951 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001952 break;
1953 default:
1954 return false;
1955 }
1956 return true;
1957}
1958
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001959void GrGpuGL::setTextureUnit(int unit) {
1960 GrAssert(unit >= 0 && unit < kNumStages);
1961 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001962 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001963 fActiveTextureUnitIdx = unit;
1964 }
1965}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001966
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001967void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001968 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1969 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001970 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1971 }
1972}
1973
reed@google.comac10a2d2010-12-22 21:39:39 +00001974/* On ES the internalFormat and format must match for TexImage and we use
1975 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1976 decide the internalFormat. However, on ES internalFormat for
1977 RenderBufferStorage* has to be a specific format (not a base format like
1978 GL_RGBA).
1979 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001980bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001981 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001982 case kRGBA_8888_GrPixelConfig:
1983 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001984 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001985 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001986 return true;
1987 } else {
1988 return false;
1989 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001990 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001991 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1992 // with FBO extension desktop GL has
1993 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001994 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001995 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001996 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001997 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001998 return true;
1999 default:
2000 return false;
2001 }
2002}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002003
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002004void GrGpuGL::resetDirtyFlags() {
2005 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2006}
2007
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002008void GrGpuGL::setBuffers(bool indexed,
2009 int* extraVertexOffset,
2010 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002011
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002012 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002013
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002014 GrGLVertexBuffer* vbuf;
2015 switch (fGeometrySrc.fVertexSrc) {
2016 case kBuffer_GeometrySrcType:
2017 *extraVertexOffset = 0;
2018 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2019 break;
2020 case kArray_GeometrySrcType:
2021 case kReserved_GeometrySrcType:
2022 finalizeReservedVertices();
2023 *extraVertexOffset = fCurrPoolStartVertex;
2024 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2025 break;
2026 default:
2027 vbuf = NULL; // suppress warning
2028 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002029 }
2030
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002031 GrAssert(NULL != vbuf);
2032 GrAssert(!vbuf->isLocked());
2033 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002034 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002035 fHWGeometryState.fArrayPtrsDirty = true;
2036 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002037 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002038
2039 if (indexed) {
2040 GrAssert(NULL != extraIndexOffset);
2041
2042 GrGLIndexBuffer* ibuf;
2043 switch (fGeometrySrc.fIndexSrc) {
2044 case kBuffer_GeometrySrcType:
2045 *extraIndexOffset = 0;
2046 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2047 break;
2048 case kArray_GeometrySrcType:
2049 case kReserved_GeometrySrcType:
2050 finalizeReservedIndices();
2051 *extraIndexOffset = fCurrPoolStartIndex;
2052 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2053 break;
2054 default:
2055 ibuf = NULL; // suppress warning
2056 GrCrash("Unknown geometry src type!");
2057 }
2058
2059 GrAssert(NULL != ibuf);
2060 GrAssert(!ibuf->isLocked());
2061 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002062 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002063 fHWGeometryState.fIndexBuffer = ibuf;
2064 }
2065 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002066}