blob: eae201950ba9068fdabf3862f370c61af900a439 [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"
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +000018#include "GrTypes.h"
bsalomon@google.com3582bf92011-06-30 21:32:31 +000019#include "SkTemplates.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000020
twiz@google.com0f31ca72011-03-18 17:38:11 +000021static const GrGLuint GR_MAX_GLUINT = ~0;
22static const GrGLint GR_INVAL_GLINT = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000023
bsalomon@google.com316f99232011-01-13 21:28:12 +000024// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000025// mucking with the state of any of the stages.
bsalomon@google.com316f99232011-01-13 21:28:12 +000026static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000027
reed@google.comac10a2d2010-12-22 21:39:39 +000028#define SKIP_CACHE_CHECK true
29
twiz@google.com0f31ca72011-03-18 17:38:11 +000030static const GrGLenum gXfermodeCoeff2Blend[] = {
31 GR_GL_ZERO,
32 GR_GL_ONE,
33 GR_GL_SRC_COLOR,
34 GR_GL_ONE_MINUS_SRC_COLOR,
35 GR_GL_DST_COLOR,
36 GR_GL_ONE_MINUS_DST_COLOR,
37 GR_GL_SRC_ALPHA,
38 GR_GL_ONE_MINUS_SRC_ALPHA,
39 GR_GL_DST_ALPHA,
40 GR_GL_ONE_MINUS_DST_ALPHA,
41 GR_GL_CONSTANT_COLOR,
42 GR_GL_ONE_MINUS_CONSTANT_COLOR,
43 GR_GL_CONSTANT_ALPHA,
44 GR_GL_ONE_MINUS_CONSTANT_ALPHA,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000045
46 // extended blend coeffs
47 GR_GL_SRC1_COLOR,
48 GR_GL_ONE_MINUS_SRC1_COLOR,
49 GR_GL_SRC1_ALPHA,
50 GR_GL_ONE_MINUS_SRC1_ALPHA,
reed@google.comac10a2d2010-12-22 21:39:39 +000051};
52
bsalomon@google.com271cffc2011-05-20 14:13:56 +000053bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
bsalomon@google.com080773c2011-03-15 19:09:25 +000054 static const bool gCoeffReferencesBlendConst[] = {
55 false,
56 false,
57 false,
58 false,
59 false,
60 false,
61 false,
62 false,
63 false,
64 false,
65 true,
66 true,
67 true,
68 true,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000069
70 // extended blend coeffs
71 false,
72 false,
73 false,
74 false,
bsalomon@google.com080773c2011-03-15 19:09:25 +000075 };
76 return gCoeffReferencesBlendConst[coeff];
bsalomon@google.com271cffc2011-05-20 14:13:56 +000077 GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
78
79 GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
80 GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
81 GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
82 GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
83 GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
84 GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
85 GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
86 GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
87 GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
88 GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
89 GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
90 GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
91 GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
92 GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
93
94 GR_STATIC_ASSERT(14 == kS2C_BlendCoeff);
95 GR_STATIC_ASSERT(15 == kIS2C_BlendCoeff);
96 GR_STATIC_ASSERT(16 == kS2A_BlendCoeff);
97 GR_STATIC_ASSERT(17 == kIS2A_BlendCoeff);
98
99 // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
100 GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
bsalomon@google.com080773c2011-03-15 19:09:25 +0000101}
102
reed@google.comac10a2d2010-12-22 21:39:39 +0000103///////////////////////////////////////////////////////////////////////////////
104
bsalomon@google.comd302f142011-03-03 13:54:13 +0000105void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
106 GrSamplerState::SampleMode mode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000107 GrMatrix* matrix) {
108 GrAssert(NULL != texture);
109 GrAssert(NULL != matrix);
110 if (GR_Scalar1 != texture->contentScaleX() ||
111 GR_Scalar1 != texture->contentScaleY()) {
112 if (GrSamplerState::kRadial_SampleMode == mode) {
113 GrMatrix scale;
114 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
115 matrix->postConcat(scale);
116 } else if (GrSamplerState::kNormal_SampleMode == mode) {
117 GrMatrix scale;
118 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
119 matrix->postConcat(scale);
120 } else {
121 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
122 }
123 }
124 GrGLTexture::Orientation orientation = texture->orientation();
125 if (GrGLTexture::kBottomUp_Orientation == orientation) {
126 GrMatrix invY;
127 invY.setAll(GR_Scalar1, 0, 0,
128 0, -GR_Scalar1, GR_Scalar1,
129 0, 0, GrMatrix::I()[8]);
130 matrix->postConcat(invY);
131 } else {
132 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
133 }
134}
135
bsalomon@google.comd302f142011-03-03 13:54:13 +0000136bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000137 const GrSamplerState& sampler) {
138 GrAssert(NULL != texture);
139 if (!sampler.getMatrix().isIdentity()) {
140 return false;
141 }
142 if (GR_Scalar1 != texture->contentScaleX() ||
143 GR_Scalar1 != texture->contentScaleY()) {
144 return false;
145 }
146 GrGLTexture::Orientation orientation = texture->orientation();
147 if (GrGLTexture::kBottomUp_Orientation == orientation) {
148 return false;
149 } else {
150 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
151 }
152 return true;
153}
154
155///////////////////////////////////////////////////////////////////////////////
156
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000157static bool gPrintStartupSpew;
158
twiz@google.com59a190b2011-03-14 21:23:01 +0000159static bool fbo_test(int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000160
twiz@google.com0f31ca72011-03-18 17:38:11 +0000161 GrGLint savedFBO;
162 GrGLint savedTexUnit;
163 GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000164 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000165
twiz@google.com0f31ca72011-03-18 17:38:11 +0000166 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000167
twiz@google.com0f31ca72011-03-18 17:38:11 +0000168 GrGLuint testFBO;
twiz@google.com59a190b2011-03-14 21:23:01 +0000169 GR_GL(GenFramebuffers(1, &testFBO));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000170 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000171 GrGLuint testRTTex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000172 GR_GL(GenTextures(1, &testRTTex));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000173 GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000174 // some implementations require texture to be mip-map complete before
175 // FBO with level 0 bound as color attachment will be framebuffer complete.
twiz@google.com0f31ca72011-03-18 17:38:11 +0000176 GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
177 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
178 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
179 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000180 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000181 GR_GL_TEXTURE_2D, testRTTex, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000182 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000183 GR_GL(DeleteFramebuffers(1, &testFBO));
reed@google.comac10a2d2010-12-22 21:39:39 +0000184 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000185
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000186 GR_GL(ActiveTexture(savedTexUnit));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000187 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000188
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000189 return status == GR_GL_FRAMEBUFFER_COMPLETE;
reed@google.comac10a2d2010-12-22 21:39:39 +0000190}
191
tomhudson@google.com747bf292011-06-14 18:16:52 +0000192static bool probe_for_npot_render_target_support(bool hasNPOTTextureSupport) {
193
194 /* Experimentation has found that some GLs that support NPOT textures
195 do not support FBOs with a NPOT texture. They report "unsupported" FBO
196 status. I don't know how to explicitly query for this. Do an
197 experiment. Note they may support NPOT with a renderbuffer but not a
198 texture. Presumably, the implementation bloats the renderbuffer
199 internally to the next POT.
200 */
201 if (hasNPOTTextureSupport) {
202 return fbo_test(200, 200);
203 }
204 return false;
205}
206
207static int probe_for_min_render_target_height(bool hasNPOTRenderTargetSupport,
208 int maxRenderTargetSize) {
209 /* The iPhone 4 has a restriction that for an FBO with texture color
210 attachment with height <= 8 then the width must be <= height. Here
211 we look for such a limitation.
212 */
213 if (gPrintStartupSpew) {
214 GrPrintf("Small height FBO texture experiments\n");
215 }
216 int minRenderTargetHeight = GR_INVAL_GLINT;
217 for (GrGLuint i = 1; i <= 256; hasNPOTRenderTargetSupport ? ++i : i *= 2) {
218 GrGLuint w = maxRenderTargetSize;
219 GrGLuint h = i;
220 if (fbo_test(w, h)) {
221 if (gPrintStartupSpew) {
222 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
223 }
224 minRenderTargetHeight = i;
225 break;
226 } else {
227 if (gPrintStartupSpew) {
228 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
229 }
230 }
231 }
232 GrAssert(GR_INVAL_GLINT != minRenderTargetHeight);
233
234 return minRenderTargetHeight;
235}
236
237static int probe_for_min_render_target_width(bool hasNPOTRenderTargetSupport,
238 int maxRenderTargetSize) {
239
240 if (gPrintStartupSpew) {
241 GrPrintf("Small width FBO texture experiments\n");
242 }
243 int minRenderTargetWidth = GR_INVAL_GLINT;
244 for (GrGLuint i = 1; i <= 256; hasNPOTRenderTargetSupport ? i *= 2 : ++i) {
245 GrGLuint w = i;
246 GrGLuint h = maxRenderTargetSize;
247 if (fbo_test(w, h)) {
248 if (gPrintStartupSpew) {
249 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
250 }
251 minRenderTargetWidth = i;
252 break;
253 } else {
254 if (gPrintStartupSpew) {
255 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
256 }
257 }
258 }
259 GrAssert(GR_INVAL_GLINT != minRenderTargetWidth);
260
261 return minRenderTargetWidth;
262}
263
264
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000265GrGpuGL::GrGpuGL()
266 : fStencilFormats(8) {
267
268 GrGLClearErr();
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000269
reed@google.comeeeb5a02010-12-23 15:12:59 +0000270 if (gPrintStartupSpew) {
271 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
272 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000273 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000274 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000275 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000276 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000277 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000278 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000279 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000280 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000281 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000282
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000283 fGLVersion = gl_version_as_float();
284 fExtensionString = (const char*) GR_GL(GetString(GR_GL_EXTENSIONS));
reed@google.comac10a2d2010-12-22 21:39:39 +0000285
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000286 this->resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000287
twiz@google.com0f31ca72011-03-18 17:38:11 +0000288 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000289 // check FS and fixed-function texture unit limits
290 // we only use textures in the fragment stage currently.
291 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000292 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
293 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
294 GrAssert(maxTextureUnits > kNumStages);
295 }
296 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
297 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
298 GrAssert(maxTextureUnits > kNumStages);
299 }
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000300 if (GR_GL_SUPPORT_ES2) {
301 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
302 &fMaxFragmentUniformVectors);
303 } else if (GR_GL_SUPPORT_DESKTOP) {
304 GrGLint max;
305 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
306 fMaxFragmentUniformVectors = max / 4;
307 } else {
308 fMaxFragmentUniformVectors = 16;
309 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000310
reed@google.comac10a2d2010-12-22 21:39:39 +0000311 ////////////////////////////////////////////////////////////////////////////
312 // Check for supported features.
313
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000314 this->setupStencilFormats();
reed@google.comac10a2d2010-12-22 21:39:39 +0000315
twiz@google.com0f31ca72011-03-18 17:38:11 +0000316 GrGLint numFormats;
317 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000318 SkAutoSTMalloc<10, GrGLint> formats(numFormats);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000319 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000320 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000321 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000322 f8bitPaletteSupport = true;
323 break;
324 }
325 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000326
327 if (gPrintStartupSpew) {
328 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
329 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000330
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000331 GR_STATIC_ASSERT(0 == kNone_GrAALevel);
332 GR_STATIC_ASSERT(1 == kLow_GrAALevel);
333 GR_STATIC_ASSERT(2 == kMed_GrAALevel);
334 GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
reed@google.comac10a2d2010-12-22 21:39:39 +0000335
336 memset(fAASamples, 0, sizeof(fAASamples));
337 fMSFBOType = kNone_MSFBO;
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000338 if (GR_GL_SUPPORT_ES) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000339 if (this->hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000340 // chrome's extension is equivalent to the EXT msaa
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000341 // and fbo_blit extensions.
342 fMSFBOType = kDesktopEXT_MSFBO;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000343 } else if (this->hasExtension("GL_APPLE_framebuffer_multisample")) {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000344 fMSFBOType = kAppleES_MSFBO;
345 }
346 } else {
347 GrAssert(GR_GL_SUPPORT_DESKTOP);
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000348 if ((fGLVersion >= 3.f) || this->hasExtension("GL_ARB_framebuffer_object")) {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000349 fMSFBOType = kDesktopARB_MSFBO;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000350 } else if (this->hasExtension("GL_EXT_framebuffer_multisample") &&
351 this->hasExtension("GL_EXT_framebuffer_blit")) {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000352 fMSFBOType = kDesktopEXT_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000353 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000354 }
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000355 if (gPrintStartupSpew) {
356 switch (fMSFBOType) {
357 case kNone_MSFBO:
358 GrPrintf("MSAA Support: NONE\n");
359 break;
360 case kDesktopARB_MSFBO:
361 GrPrintf("MSAA Support: DESKTOP ARB.\n");
362 break;
363 case kDesktopEXT_MSFBO:
364 GrPrintf("MSAA Support: DESKTOP EXT.\n");
365 break;
366 case kAppleES_MSFBO:
367 GrPrintf("MSAA Support: APPLE ES.\n");
368 break;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000369 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000370 }
371
372 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000373 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000374 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000375 if (maxSamples > 1 ) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000376 fAASamples[kNone_GrAALevel] = 0;
377 fAASamples[kLow_GrAALevel] = GrMax(2,
378 GrFixedFloorToInt((GR_FixedHalf) *
379 maxSamples));
380 fAASamples[kMed_GrAALevel] = GrMax(2,
381 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
382 maxSamples));
383 fAASamples[kHigh_GrAALevel] = maxSamples;
reed@google.comac10a2d2010-12-22 21:39:39 +0000384 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000385 if (gPrintStartupSpew) {
386 GrPrintf("\tMax Samples: %d\n", maxSamples);
387 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000388 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +0000389 fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000390
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000391 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000392 fHasStencilWrap = (fGLVersion >= 1.4f) ||
393 this->hasExtension("GL_EXT_stencil_wrap");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000394 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000395 fHasStencilWrap = (fGLVersion >= 2.0f) || this->hasExtension("GL_OES_stencil_wrap");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000396 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000397 if (gPrintStartupSpew) {
398 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
399 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000400
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000401 if (GR_GL_SUPPORT_DESKTOP) {
402 // we could also look for GL_ATI_separate_stencil extension or
403 // GL_EXT_stencil_two_side but they use different function signatures
404 // than GL2.0+ (and than each other).
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000405 fTwoSidedStencilSupport = (fGLVersion >= 2.f);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000406 // supported on GL 1.4 and higher or by extension
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000407 fStencilWrapOpsSupport = (fGLVersion >= 1.4f) ||
408 this->hasExtension("GL_EXT_stencil_wrap");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000409 } else {
410 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
411 // an ES1 extension.
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000412 fTwoSidedStencilSupport = (fGLVersion >= 2.f);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000413 // stencil wrap support is in ES2, ES1 requires extension.
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000414 fStencilWrapOpsSupport = (fGLVersion >= 2.f) ||
415 this->hasExtension("GL_OES_stencil_wrap");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000416 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000417 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000418 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
419 (fTwoSidedStencilSupport ? "YES" : "NO"),
420 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000421 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000422
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000423 if (GR_GL_SUPPORT_DESKTOP) {
424 fRGBA8Renderbuffer = true;
425 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000426 fRGBA8Renderbuffer = this->hasExtension("GL_OES_rgb8_rgba8");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000427 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000428 if (gPrintStartupSpew) {
429 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
430 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000431
432
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000433 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000434 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000435 GrAssert(this->hasExtension("GL_EXT_texture_format_BGRA8888"));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000436 }
437 }
438
439 if (GR_GL_SUPPORT_DESKTOP) {
440 fBufferLockSupport = true; // we require VBO support and the desktop VBO
441 // extension includes glMapBuffer.
442 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000443 fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000444 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000445
reed@google.comeeeb5a02010-12-23 15:12:59 +0000446 if (gPrintStartupSpew) {
447 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
448 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000449
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000450 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000451 if (fGLVersion >= 2.f ||
452 this->hasExtension("GL_ARB_texture_non_power_of_two")) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000453 fNPOTTextureTileSupport = true;
454 fNPOTTextureSupport = true;
455 } else {
456 fNPOTTextureTileSupport = false;
457 fNPOTTextureSupport = false;
458 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000459 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000460 if (fGLVersion >= 2.f) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000461 fNPOTTextureSupport = true;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000462 fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000463 } else {
464 fNPOTTextureSupport =
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000465 this->hasExtension("GL_APPLE_texture_2D_limited_npot");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000466 fNPOTTextureTileSupport = false;
467 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000468 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000469
bsalomon@google.com205d4602011-04-25 12:43:45 +0000470 fAALineSupport = GR_GL_SUPPORT_DESKTOP;
471
reed@google.comac10a2d2010-12-22 21:39:39 +0000472 ////////////////////////////////////////////////////////////////////////////
tomhudson@google.com747bf292011-06-14 18:16:52 +0000473 // Experiments to determine limitations that can't be queried.
474 // TODO: Make these a preprocess that generate some compile time constants.
475 // TODO: probe once at startup, rather than once per context creation.
reed@google.comac10a2d2010-12-22 21:39:39 +0000476
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000477 int expectNPOTTargets = GrGLGetGLInterface()->fNPOTRenderTargetSupport;
478 if (expectNPOTTargets == kProbe_GrGLCapability) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000479 fNPOTRenderTargetSupport =
480 probe_for_npot_render_target_support(fNPOTTextureSupport);
tomhudson@google.com30e4bb62011-06-15 19:41:46 +0000481 } else {
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000482 GrAssert(expectNPOTTargets == 0 || expectNPOTTargets == 1);
483 fNPOTRenderTargetSupport = static_cast<bool>(expectNPOTTargets);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000484 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000485
bsalomon@google.com0748f212011-02-01 22:56:16 +0000486 if (gPrintStartupSpew) {
487 if (fNPOTTextureSupport) {
488 GrPrintf("NPOT textures supported\n");
489 if (fNPOTTextureTileSupport) {
490 GrPrintf("NPOT texture tiling supported\n");
491 } else {
492 GrPrintf("NPOT texture tiling NOT supported\n");
493 }
494 if (fNPOTRenderTargetSupport) {
495 GrPrintf("NPOT render targets supported\n");
496 } else {
497 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000498 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000499 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000500 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000501 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000502 }
503
bsalomon@google.com91958362011-06-13 17:58:13 +0000504 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
505 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
tomhudson@google.com747bf292011-06-14 18:16:52 +0000506 // Our render targets are always created with textures as the color
bsalomon@google.com91958362011-06-13 17:58:13 +0000507 // attachment, hence this min:
508 fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000509
tomhudson@google.com747bf292011-06-14 18:16:52 +0000510 fMinRenderTargetHeight = GrGLGetGLInterface()->fMinRenderTargetHeight;
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000511 if (fMinRenderTargetHeight == kProbe_GrGLCapability) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000512 fMinRenderTargetHeight =
513 probe_for_min_render_target_height(fNPOTRenderTargetSupport,
514 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000515 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000516
tomhudson@google.com747bf292011-06-14 18:16:52 +0000517 fMinRenderTargetWidth = GrGLGetGLInterface()->fMinRenderTargetWidth;
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000518 if (fMinRenderTargetWidth == kProbe_GrGLCapability) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000519 fMinRenderTargetWidth =
520 probe_for_min_render_target_width(fNPOTRenderTargetSupport,
521 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000522 }
tomhudson@google.com747bf292011-06-14 18:16:52 +0000523
bsalomon@google.comfe676522011-06-17 18:12:21 +0000524 fLastSuccessfulStencilFmtIdx = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000525}
526
527GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000528}
529
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000530void GrGpuGL::resetContext() {
531 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000532 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000533 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000534
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000535 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000536 GR_GL(Disable(GR_GL_DEPTH_TEST));
537 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000538
twiz@google.com0f31ca72011-03-18 17:38:11 +0000539 GR_GL(Disable(GR_GL_CULL_FACE));
540 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000541 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000542
twiz@google.com0f31ca72011-03-18 17:38:11 +0000543 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000544 if (GR_GL_SUPPORT_DESKTOP) {
545 GR_GL(Disable(GR_GL_LINE_SMOOTH));
546 GR_GL(Disable(GR_GL_POINT_SMOOTH));
547 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000548 fHWAAState.fMSAAEnabled = false;
549 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000550 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000551
twiz@google.com0f31ca72011-03-18 17:38:11 +0000552 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000553 fHWDrawState.fFlagBits = 0;
554
reed@google.comac10a2d2010-12-22 21:39:39 +0000555 // we only ever use lines in hairline mode
556 GR_GL(LineWidth(1));
557
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000558 // invalid
559 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000560
reed@google.comac10a2d2010-12-22 21:39:39 +0000561 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000562 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
563 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000564
565 fHWDrawState.fBlendConstant = 0x00000000;
566 GR_GL(BlendColor(0,0,0,0));
567
reed@google.comac10a2d2010-12-22 21:39:39 +0000568 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000569
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000570 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000571
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000572 for (int s = 0; s < kNumStages; ++s) {
573 fHWDrawState.fTextures[s] = NULL;
574 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
575 -GR_ScalarMax,
576 true);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000577 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000578 fHWDrawState.fSamplerStates[s].setConvolutionParams(0, NULL, NULL);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000579 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000580
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000581 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000582 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000583 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000584 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000585
bsalomon@google.comd302f142011-03-03 13:54:13 +0000586 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000587 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000588 fClipState.fClipIsDirty = true;
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000589 fClipState.fClipInStencil = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000590
591 fHWGeometryState.fIndexBuffer = NULL;
592 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000593
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000594 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000595
twiz@google.com0f31ca72011-03-18 17:38:11 +0000596 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000597 fHWDrawState.fRenderTarget = NULL;
598}
599
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000600GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
601
602 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
603 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
604 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
605 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
606
607 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
608 if (isRenderTarget) {
609 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
610 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
611 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
612 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
613 } else {
614 GrAssert(!isTexture); // this should have been filtered by GrContext
615 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
616 }
617 } else {
618 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
619 }
620 // we don't know what the RB ids are without glGets and we don't care
621 // since we aren't responsible for deleting them.
622 rtIDs.fStencilRenderbufferID = 0;
623 rtIDs.fMSColorRenderbufferID = 0;
624
625 rtIDs.fOwnIDs = false;
626 } else {
627 rtIDs.reset();
628 }
629
630 if (isTexture) {
631 GrGLTexture::GLTextureDesc texDesc;
632 GrGLenum dontCare;
633 if (!canBeTexture(desc.fConfig, &dontCare,
634 &texDesc.fUploadFormat,
635 &texDesc.fUploadType)) {
636 return NULL;
637 }
638
639 GrGLTexture::TexParams params;
640
641 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
642 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
643
bsalomon@google.com90405932011-06-17 15:56:55 +0000644 texDesc.fFormat = desc.fConfig;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000645 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
646 texDesc.fStencilBits = desc.fStencilBits;
647 texDesc.fTextureID = desc.fPlatformTexture;
648 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
649 texDesc.fOwnsID = false;
650
651 params.invalidate(); // rather than do glGets.
652
653 return new GrGLTexture(this, texDesc, rtIDs, params);
654 } else {
655 GrGLIRect viewport;
656 viewport.fLeft = 0;
657 viewport.fBottom = 0;
658 viewport.fWidth = desc.fWidth;
659 viewport.fHeight = desc.fHeight;
660
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000661 bool isMSAA = kIsMultisampled_GrPlatformRenderTargetFlagBit &
662 desc.fRenderTargetFlags;
663
664 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fConfig,
665 desc.fStencilBits, isMSAA, viewport, NULL);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000666 }
667}
668
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000669namespace {
670
671static const GrGLenum kUnknownGLFormat = ~0;
672
673GrGLenum get_fbo_color_format() {
674 GrGLint cbType;
675 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
676 GR_GL_COLOR_ATTACHMENT0,
677 GR_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
678 &cbType);
679 GrGLint cbID;
680 GrGLint cbFormat;
681 switch (cbType) {
682 case GR_GL_RENDERBUFFER:
683 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
684 GR_GL_COLOR_ATTACHMENT0,
685 GR_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
686 &cbID);
687 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER, cbID));
688 GR_GL_GetRenderbufferParameteriv(GR_GL_RENDERBUFFER,
689 GR_GL_RENDERBUFFER_INTERNAL_FORMAT,
690 &cbFormat);
691 return cbFormat;
692 break;
693 case GR_GL_TEXTURE:
694 // ES doesn't have glGetTexLevelParameter
695 if (GR_GL_SUPPORT_DESKTOP) {
696 GrGLint cbLevel;
697 GrGLint cbFace;
698 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
699 GR_GL_COLOR_ATTACHMENT0,
700 GR_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
701 &cbID);
702 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
703 GR_GL_COLOR_ATTACHMENT0,
704 GR_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
705 &cbLevel);
706 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
707 GR_GL_COLOR_ATTACHMENT0,
708 GR_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
709 &cbFace);
710 GrGLenum bind;
711 GrGLenum target;
712 if (cbFace) {
713 bind = GR_GL_TEXTURE_CUBE_MAP;
714 target = cbFace;
715 } else {
716 bind = GR_GL_TEXTURE_2D;
717 target = GR_GL_TEXTURE_2D;
718 }
719 GR_GL(BindTexture(bind, cbID));
720 GR_GL_GetTexLevelParameteriv(target, cbLevel,
721 GR_GL_TEXTURE_INTERNAL_FORMAT, &cbFormat);
722 return cbFormat;
723 } else {
724 return kUnknownGLFormat;
725 }
726 break;
727 default:
728 // we can get here with FBO 0, not a render buffer or a texture
729 return kUnknownGLFormat;
730 }
731}
732
733GrPixelConfig internal_color_format_to_config(GrGLenum iFormat) {
734 switch (iFormat) {
735 case GR_GL_RGB565:
736 return kRGB_565_GrPixelConfig;
737 case GR_GL_RGBA4:
738 return kRGBA_4444_GrPixelConfig;
739 case GR_GL_RGBA8:
740 case GR_GL_SRGB8_ALPHA8:
741 case GR_GL_SRGB_ALPHA:
742 case GR_GL_RGBA:
743 case GR_GL_BGRA:
744 return kRGBA_8888_GrPixelConfig;
745 case GR_GL_RGB8:
746 case GR_GL_SRGB8:
747 case GR_GL_SRGB:
748 return kRGBX_8888_GrPixelConfig;
749 default:
750 // there are many GL formats we don't have enums
751 // for. We should still render to them if the client
752 // asks us.
753 return kUnknown_GrPixelConfig;
754 }
755}
756
757GrPixelConfig get_implied_color_config(bool arbFBOExtension) {
758 GrGLint rSize, bSize, gSize, aSize;
759 if (arbFBOExtension) {
760 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
761 GR_GL_COLOR_ATTACHMENT0,
762 GR_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &rSize);
763 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
764 GR_GL_COLOR_ATTACHMENT0,
765 GR_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &gSize);
766 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
767 GR_GL_COLOR_ATTACHMENT0,
768 GR_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &bSize);
769 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
770 GR_GL_COLOR_ATTACHMENT0,
771 GR_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &aSize);
772 } else {
773 GR_GL_GetIntegerv(GR_GL_RED_BITS, &rSize);
774 GR_GL_GetIntegerv(GR_GL_GREEN_BITS, &gSize);
775 GR_GL_GetIntegerv(GR_GL_BLUE_BITS, &bSize);
776 GR_GL_GetIntegerv(GR_GL_ALPHA_BITS, &aSize);
777 }
778
779 if(8 == rSize && 8 == gSize && 8 == bSize) {
780 if (0 == aSize) {
781 return kRGBX_8888_GrPixelConfig;
782 } else if (8 == aSize) {
783 return kRGBA_8888_GrPixelConfig;
784 }
785 } else if (4 == rSize && 4 == gSize && 4 == bSize && 4 == aSize) {
786 return kRGBA_4444_GrPixelConfig;
787 } else if (5 == rSize && 6 == gSize && 5 == bSize && 0 == aSize) {
788 return kRGB_565_GrPixelConfig;
789 }
790 return kUnknown_GrPixelConfig;
791}
792
793int get_fbo_stencil_bits(bool arbFBOExtension) {
794 GrGLint stencilBits;
795 if (arbFBOExtension) {
796 GR_GL_GetFramebufferAttachmentParameteriv(GR_GL_FRAMEBUFFER,
797 GR_GL_STENCIL_ATTACHMENT,
798 GR_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
799 &stencilBits);
800 } else {
801 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, &stencilBits);
802 }
803 return stencilBits;
804}
805}
806
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000807GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000808
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000809 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000810
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000811 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000812 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
813 rtIDs.fMSColorRenderbufferID = 0;
814 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000815
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000816 bool arbFBO = (GR_GL_SUPPORT_DESKTOP && (fGLVersion > 3.0 ||
817 this->hasExtension("GL_ARB_framebuffer_object")));
818
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000819 GrGLIRect viewport;
820 viewport.setFromGLViewport();
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000821 int stencilBits = get_fbo_stencil_bits(arbFBO);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000822
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000823 GrPixelConfig config;
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000824 GrGLint samples;
825 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000826 GrGLenum fmat = get_fbo_color_format();
827 if (kUnknownGLFormat == fmat) {
828 config = get_implied_color_config(arbFBO);
829 } else {
830 config = internal_color_format_to_config(fmat);
831 }
832
833 // may have to bind a texture to gets its format
834 this->setSpareTextureUnit();
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000835
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000836 rtIDs.fOwnIDs = false;
837
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000838 return new GrGLRenderTarget(this, rtIDs, NULL, config, stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000839 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000840}
841
bsalomon@google.com5782d712011-01-21 21:03:59 +0000842///////////////////////////////////////////////////////////////////////////////
843
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000844void GrGpuGL::setupStencilFormats() {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000845
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000846 // Build up list of legal stencil formats (though perhaps not supported on
847 // the particular gpu/driver) from most preferred to least.
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000848
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000849 // these consts are in order of most preferred to least preferred
850 // we don't bother with GL_STENCIL_INDEX1 or GL_DEPTH32F_STENCIL8
851 static const StencilFormat gS8 = {GR_GL_STENCIL_INDEX8, 8, false};
852 static const StencilFormat gS16 = {GR_GL_STENCIL_INDEX16, 16, false};
853 static const StencilFormat gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, true };
854 static const StencilFormat gS4 = {GR_GL_STENCIL_INDEX4, 4, false};
855 static const StencilFormat gS = {GR_GL_STENCIL_INDEX, gUNKNOWN_BITCOUNT, false};
856 static const StencilFormat gDS = {GR_GL_DEPTH_STENCIL, gUNKNOWN_BITCOUNT, true };
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000857
858 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000859 bool supportsPackedDS = fGLVersion >= 3.0f ||
860 this->hasExtension("GL_EXT_packed_depth_stencil") ||
861 this->hasExtension("GL_ARB_framebuffer_object");
862
863 // S1 thru S16 formats are in GL 3.0+, EXT_FBO, and ARB_FBO since we
864 // require FBO support we can expect these are legal formats and don't
865 // check. These also all support the unsized GL_STENCIL_INDEX.
866 fStencilFormats.push_back() = gS8;
867 fStencilFormats.push_back() = gS16;
868 if (supportsPackedDS) {
869 fStencilFormats.push_back() = gD24S8;
870 }
871 fStencilFormats.push_back() = gS4;
872 if (supportsPackedDS) {
873 fStencilFormats.push_back() = gDS;
874 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000875 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000876 // ES2 has STENCIL_INDEX8 without extensions.
877 // ES1 with GL_OES_framebuffer_object (which we require for ES1)
878 // introduces tokens for S1 thu S8 but there are separate extensions
879 // that make them legal (GL_OES_stencil1, ...).
880 // GL_OES_packed_depth_stencil adds DEPTH24_STENCIL8
881 // ES doesn't support using the unsized formats.
882
883 if (fGLVersion >= 2.f || this->hasExtension("GL_OES_stencil8")) {
884 fStencilFormats.push_back() = gS8;
885 }
886 //fStencilFormats.push_back() = gS16;
887 if (this->hasExtension("GL_OES_packed_depth_stencil")) {
888 fStencilFormats.push_back() = gD24S8;
889 }
890 if (this->hasExtension("GL_OES_stencil4")) {
891 fStencilFormats.push_back() = gS4;
892 }
893 // we require some stencil format.
894 GrAssert(fStencilFormats.count() > 0);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000895 }
896}
897
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000898// good to set a break-point here to know when createTexture fails
899static GrTexture* return_null_texture() {
900// GrAssert(!"null texture");
901 return NULL;
902}
903
904#if GR_DEBUG
905static size_t as_size_t(int x) {
906 return x;
907}
908#endif
909
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000910GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000911 const void* srcData,
912 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000913
914#if GR_COLLECT_STATS
915 ++fStats.fTextureCreateCnt;
916#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000917
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000918 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000919
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000920 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000921 GR_GL_NEAREST,
922 GR_GL_CLAMP_TO_EDGE,
923 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000924 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000925
reed@google.comac10a2d2010-12-22 21:39:39 +0000926 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000927 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000928
929 glDesc.fContentWidth = desc.fWidth;
930 glDesc.fContentHeight = desc.fHeight;
931 glDesc.fAllocWidth = desc.fWidth;
932 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000933 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000934 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000935 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000936
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000937 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000938 if (!canBeTexture(desc.fFormat,
939 &internalFormat,
940 &glDesc.fUploadFormat,
941 &glDesc.fUploadType)) {
942 return return_null_texture();
943 }
944
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000945 // We keep GrRenderTargets in GL's normal orientation so that they
946 // can be drawn to by the outside world without the client having
947 // to render upside down.
948 glDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
949 GrGLTexture::kTopDown_Orientation;
950
reed@google.comac10a2d2010-12-22 21:39:39 +0000951 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000952 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000953 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000954 GrPrintf("AA RT requested but not supported on this platform.");
955 }
956
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000957 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000958
reed@google.com5e762232011-04-04 18:15:49 +0000959 // in case we need a temporary, trimmed copy of the src pixels
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000960 SkAutoSMalloc<128 * 128> tempStorage;
reed@google.com5e762232011-04-04 18:15:49 +0000961
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000962 if (!rowBytes) {
963 rowBytes = glDesc.fUploadByteCount * desc.fWidth;
964 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000965 /*
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000966 * check whether to allocate a temporary buffer for flipping y or
967 * because our srcData has extra bytes past each row. If so, we need
968 * to trim those off here, since GL ES doesn't let us specify
969 * GL_UNPACK_ROW_LENGTH.
reed@google.comac10a2d2010-12-22 21:39:39 +0000970 */
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000971 bool flipY = GrGLTexture::kBottomUp_Orientation == glDesc.fOrientation;
972 if (GR_GL_SUPPORT_DESKTOP && !flipY) {
973 if (srcData && rowBytes != desc.fWidth * glDesc.fUploadByteCount) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000974 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
975 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000976 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000977 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000978 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000979 if (srcData && (trimRowBytes < rowBytes || flipY)) {
reed@google.com5e762232011-04-04 18:15:49 +0000980 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000981 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000982 const char* src = (const char*)srcData;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000983 if (flipY) {
984 src += (desc.fHeight - 1) * rowBytes;
985 }
986 char* dst = (char*)tempStorage.realloc(trimSize);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000987 for (int y = 0; y < desc.fHeight; y++) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000988 memcpy(dst, src, trimRowBytes);
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000989 if (flipY) {
990 src -= rowBytes;
991 } else {
992 src += rowBytes;
993 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000994 dst += trimRowBytes;
995 }
996 // now point srcData to our trimmed version
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000997 srcData = tempStorage.get();
998 rowBytes = trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000999 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001000 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001001
reed@google.comac10a2d2010-12-22 21:39:39 +00001002 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +00001003 if (!this->npotRenderTargetSupport()) {
1004 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
1005 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
1006 }
1007
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +00001008 glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
1009 glDesc.fAllocWidth);
1010 glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
1011 glDesc.fAllocHeight);
1012 if (glDesc.fAllocWidth > fMaxRenderTargetSize ||
1013 glDesc.fAllocHeight > fMaxRenderTargetSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +00001014 return return_null_texture();
1015 }
bsalomon@google.com0748f212011-02-01 22:56:16 +00001016 } else if (!this->npotTextureSupport()) {
1017 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
1018 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +00001019 if (glDesc.fAllocWidth > fMaxTextureSize ||
1020 glDesc.fAllocHeight > fMaxTextureSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +00001021 return return_null_texture();
1022 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001023 }
1024
bsalomon@google.comd9f826c2011-07-18 15:25:04 +00001025 GR_GL(GenTextures(1, &glDesc.fTextureID));
1026 if (!glDesc.fTextureID) {
1027 return return_null_texture();
1028 }
1029
twiz@google.com0f31ca72011-03-18 17:38:11 +00001030 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
1031 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1032 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +00001033 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001034 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1035 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +00001036 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001037 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1038 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +00001039 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001040 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1041 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +00001042 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001043
twiz@google.com0f31ca72011-03-18 17:38:11 +00001044 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001045 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +00001046 supports8BitPalette()) {
1047 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
1048 GrAssert(desc.fWidth == glDesc.fAllocWidth);
1049 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001050 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001051 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001052 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +00001053 glDesc.fAllocWidth, glDesc.fAllocHeight,
1054 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +00001055 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +00001056 } else {
1057 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
1058 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001059 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +00001060 glDesc.fAllocWidth, glDesc.fAllocHeight,
1061 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001062 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +00001063 desc.fHeight, glDesc.fUploadFormat,
1064 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +00001065 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +00001066
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +00001067 int extraW = glDesc.fAllocWidth - desc.fWidth;
1068 int extraH = glDesc.fAllocHeight - desc.fHeight;
1069 int maxTexels = extraW * extraH;
reed@google.comac10a2d2010-12-22 21:39:39 +00001070 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
1071 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
1072
bsalomon@google.com3582bf92011-06-30 21:32:31 +00001073 SkAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
reed@google.comac10a2d2010-12-22 21:39:39 +00001074
bsalomon@google.comd9f826c2011-07-18 15:25:04 +00001075 // rowBytes is actual stride between rows in srcData
1076 // rowDataBytes is the actual amount of non-pad data in a row
1077 // and the stride used for uploading extraH rows.
1078 uint32_t rowDataBytes = desc.fWidth * glDesc.fUploadByteCount;
reed@google.comac10a2d2010-12-22 21:39:39 +00001079 if (extraH) {
1080 uint8_t* lastRowStart = (uint8_t*) srcData +
bsalomon@google.comd9f826c2011-07-18 15:25:04 +00001081 (desc.fHeight - 1) * rowBytes;
reed@google.comac10a2d2010-12-22 21:39:39 +00001082 uint8_t* extraRowStart = (uint8_t*)texels.get();
1083
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +00001084 for (int i = 0; i < extraH; ++i) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +00001085 memcpy(extraRowStart, lastRowStart, rowDataBytes);
1086 extraRowStart += rowDataBytes;
reed@google.comac10a2d2010-12-22 21:39:39 +00001087 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001088 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +00001089 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
1090 texels.get()));
1091 }
1092 if (extraW) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +00001093 uint8_t* edgeTexel = (uint8_t*)srcData + rowDataBytes - glDesc.fUploadByteCount;
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +00001095 for (int j = 0; j < desc.fHeight; ++j) {
1096 for (int i = 0; i < extraW; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
1098 extraTexel += glDesc.fUploadByteCount;
1099 }
bsalomon@google.comd9f826c2011-07-18 15:25:04 +00001100 edgeTexel += rowBytes;
reed@google.comac10a2d2010-12-22 21:39:39 +00001101 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001102 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +00001103 desc.fHeight, glDesc.fUploadFormat,
1104 glDesc.fUploadType, texels.get()));
1105 }
1106 if (extraW && extraH) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +00001107 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowBytes
reed@google.comac10a2d2010-12-22 21:39:39 +00001108 - glDesc.fUploadByteCount;
1109 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +00001110 for (int i = 0; i < extraW*extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001111 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
1112 extraTexel += glDesc.fUploadByteCount;
1113 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001114 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +00001115 extraW, extraH, glDesc.fUploadFormat,
1116 glDesc.fUploadType, texels.get()));
1117 }
1118
1119 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001120 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +00001121 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
1122 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +00001123 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +00001124 }
1125 }
1126
reed@google.comac10a2d2010-12-22 21:39:39 +00001127
1128 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
1129 rtIDs.fStencilRenderbufferID = 0;
1130 rtIDs.fMSColorRenderbufferID = 0;
1131 rtIDs.fRTFBOID = 0;
1132 rtIDs.fTexFBOID = 0;
1133 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001134 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +00001135
1136 if (renderTarget) {
1137#if GR_COLLECT_STATS
1138 ++fStats.fRenderTargetCreateCnt;
1139#endif
1140 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001141 GrGLenum status;
1142 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +00001143
twiz@google.com59a190b2011-03-14 21:23:01 +00001144 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001145 GrAssert(rtIDs.fTexFBOID);
1146
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001147 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001148 // to one and then resolve to the texture bound to the other.
1149 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001150 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001151 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +00001152 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001153 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
1154 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001155 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +00001157 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
1158 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001159 return return_null_texture();
1160 }
1161 } else {
1162 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
1163 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001164 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001165 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001166 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +00001167 }
1168
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001169 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +00001170 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001171 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +00001172 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001173
twiz@google.com0f31ca72011-03-18 17:38:11 +00001174 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001175
bsalomon@google.comfe676522011-06-17 18:12:21 +00001176 int stencilFmtCnt;
bsalomon@google.comfe676522011-06-17 18:12:21 +00001177 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001178 stencilFmtCnt = fStencilFormats.count();
bsalomon@google.comfe676522011-06-17 18:12:21 +00001179 } else {
1180 stencilFmtCnt = 1; // only 1 attempt when we don't need a stencil
1181 }
1182
1183 for (int i = 0; i < stencilFmtCnt; ++i) {
1184 // we start with the last stencil format that succeeded in hopes
1185 // that we won't go through this loop more than once after the
1186 // first (painful) stencil creation.
1187 int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
1188
reed@google.comac10a2d2010-12-22 21:39:39 +00001189 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001190 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001191 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001192 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001193 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001194 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001195 samples,
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001196 fStencilFormats[sIdx].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +00001197 glDesc.fAllocWidth,
1198 glDesc.fAllocHeight));
1199 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001200 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001201 fStencilFormats[sIdx].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +00001202 glDesc.fAllocWidth,
1203 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +00001204 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001205 err = GrGLGetGLInterface()->fGetError();
1206 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001207 continue;
1208 }
1209 }
1210 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
1211 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001212 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001213 rtIDs.fMSColorRenderbufferID));
1214 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001215 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001216 samples,
1217 msColorRenderbufferFormat,
1218 glDesc.fAllocWidth,
1219 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001220 err = GrGLGetGLInterface()->fGetError();
1221 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001222 continue;
1223 }
1224 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001225 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001226
1227#if GR_COLLECT_STATS
1228 ++fStats.fRenderTargetChngCnt;
1229#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001230 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1231 GR_GL_COLOR_ATTACHMENT0,
1232 GR_GL_TEXTURE_2D,
1233 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001234 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001235 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1236 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001237 continue;
1238 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001239 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001240 #if GR_COLLECT_STATS
1241 ++fStats.fRenderTargetChngCnt;
1242 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001243 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1244 GR_GL_COLOR_ATTACHMENT0,
1245 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001246 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001247
1248 }
1249 if (rtIDs.fStencilRenderbufferID) {
1250 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001251 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1252 GR_GL_STENCIL_ATTACHMENT,
1253 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001254 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001255 // if it is a packed format bind to depth also, otherwise
1256 // we may get an unsupported fbo completeness result
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001257 if (fStencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001258 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1259 GR_GL_DEPTH_ATTACHMENT,
1260 GR_GL_RENDERBUFFER,
1261 rtIDs.fStencilRenderbufferID));
1262 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001263 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001264 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001265
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001266 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001267 // undo the depth bind
1268 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001269 fStencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001270 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1271 GR_GL_DEPTH_ATTACHMENT,
1272 GR_GL_RENDERBUFFER,
1273 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001274 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001275 continue;
1276 }
1277 // we're successful!
1278 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001279 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comfe676522011-06-17 18:12:21 +00001280 fLastSuccessfulStencilFmtIdx = sIdx;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001281 if (gUNKNOWN_BITCOUNT == fStencilFormats[sIdx].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001282 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001283 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001284 glDesc.fStencilBits = fStencilFormats[sIdx].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001285 }
1286 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001287 break;
1288 }
1289 if (failed) {
1290 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001291 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001292 }
1293 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001294 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001295 }
1296 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001297 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001298 }
1299 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001300 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001301 }
1302 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1303 return return_null_texture();
1304 }
1305 }
1306#ifdef TRACE_TEXTURE_CREATION
1307 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1308 tex->fTextureID, width, height, tex->fUploadByteCount);
1309#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001310 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001311
1312 if (0 != rtIDs.fTexFBOID) {
1313 GrRenderTarget* rt = tex->asRenderTarget();
1314 // We've messed with FBO state but may not have set the correct viewport
1315 // so just dirty the rendertarget state to force a resend.
1316 fHWDrawState.fRenderTarget = NULL;
1317
1318 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001319 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001320 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1321 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001322 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001323 fCurrDrawState.fRenderTarget = rtSave;
1324 }
1325 }
1326 return tex;
1327}
1328
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001329GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001330 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001331 GR_GL(GenBuffers(1, &id));
1332 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001333 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001334 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001335 GrGLClearErr();
1336 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001337 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1338 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1339 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001340 GR_GL(DeleteBuffers(1, &id));
1341 // deleting bound buffer does implicit bind to 0
1342 fHWGeometryState.fVertexBuffer = NULL;
1343 return NULL;
1344 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001345 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001346 size, dynamic);
1347 fHWGeometryState.fVertexBuffer = vertexBuffer;
1348 return vertexBuffer;
1349 }
1350 return NULL;
1351}
1352
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001353GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001354 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001355 GR_GL(GenBuffers(1, &id));
1356 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001357 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001358 GrGLClearErr();
1359 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001360 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1361 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1362 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001363 GR_GL(DeleteBuffers(1, &id));
1364 // deleting bound buffer does implicit bind to 0
1365 fHWGeometryState.fIndexBuffer = NULL;
1366 return NULL;
1367 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001368 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001369 size, dynamic);
1370 fHWGeometryState.fIndexBuffer = indexBuffer;
1371 return indexBuffer;
1372 }
1373 return NULL;
1374}
1375
reed@google.comac10a2d2010-12-22 21:39:39 +00001376void GrGpuGL::flushScissor(const GrIRect* rect) {
1377 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001378 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001379 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001380
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001381 GrGLIRect scissor;
1382 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001383 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001384 rect->width(), rect->height());
1385 if (scissor.contains(vp)) {
1386 rect = NULL;
1387 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001388 }
1389
1390 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001391 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001392 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001393 fHWBounds.fScissorRect = scissor;
1394 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001395 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001396 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001397 fHWBounds.fScissorEnabled = true;
1398 }
1399 } else {
1400 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001401 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001402 fHWBounds.fScissorEnabled = false;
1403 }
1404 }
1405}
1406
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001407void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001408 if (NULL == fCurrDrawState.fRenderTarget) {
1409 return;
1410 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001411 GrIRect r;
1412 if (NULL != rect) {
1413 // flushScissor expects rect to be clipped to the target.
1414 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001415 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1416 fCurrDrawState.fRenderTarget->height());
1417 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001418 rect = &r;
1419 } else {
1420 return;
1421 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001422 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001423 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001424 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001425 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001426 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001427 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1428 GrColorUnpackG(color)/255.f,
1429 GrColorUnpackB(color)/255.f,
1430 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001431 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001432}
1433
bsalomon@google.com398109c2011-04-14 18:40:27 +00001434void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001435 if (NULL == fCurrDrawState.fRenderTarget) {
1436 return;
1437 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001438
1439 this->flushRenderTarget(&GrIRect::EmptyIRect());
1440
reed@google.comac10a2d2010-12-22 21:39:39 +00001441 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001442 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001443 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001444 }
1445 GR_GL(StencilMask(mask));
1446 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001447 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001448 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001449}
1450
bsalomon@google.com398109c2011-04-14 18:40:27 +00001451void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001452 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001453#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001454 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001455 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001456 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001457#else
1458 // we could just clear the clip bit but when we go through
1459 // angle a partial stencil mask will cause clears to be
1460 // turned into draws. Our contract on GrDrawTarget says that
1461 // changing the clip between stencil passes may or may not
1462 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001463 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001464#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001465 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001466 flushScissor(&rect);
1467 GR_GL(StencilMask(clipStencilMask));
1468 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001469 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001470 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001471}
1472
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001473void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001474 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001475}
1476
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001477bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1478 int left, int top, int width, int height,
1479 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001480 GrGLenum internalFormat; // we don't use this for glReadPixels
1481 GrGLenum format;
1482 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001483 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1484 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001485 }
1486 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1487 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1488 switch (tgt->getResolveType()) {
1489 case GrGLRenderTarget::kCantResolve_ResolveType:
1490 return false;
1491 case GrGLRenderTarget::kAutoResolves_ResolveType:
1492 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1493 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001494 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001495 break;
1496 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001497 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001498 // we don't track the state of the READ FBO ID.
1499 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1500 break;
1501 default:
1502 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001503 }
1504
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001505 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001506
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001507 // the read rect is viewport-relative
1508 GrGLIRect readRect;
1509 readRect.setRelativeTo(glvp, left, top, width, height);
1510 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001511 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001512 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001513
1514 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1515 // API presents top-to-bottom
1516 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001517 size_t stride = width * GrBytesPerPixel(config);
bsalomon@google.com3582bf92011-06-30 21:32:31 +00001518 SkAutoMalloc rowStorage(stride);
reed@google.comac10a2d2010-12-22 21:39:39 +00001519 void* tmp = rowStorage.get();
1520
1521 const int halfY = height >> 1;
1522 char* top = reinterpret_cast<char*>(buffer);
1523 char* bottom = top + (height - 1) * stride;
1524 for (int y = 0; y < halfY; y++) {
1525 memcpy(tmp, top, stride);
1526 memcpy(top, bottom, stride);
1527 memcpy(bottom, tmp, stride);
1528 top += stride;
1529 bottom -= stride;
1530 }
1531 }
1532 return true;
1533}
1534
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001535void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001536
1537 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1538
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001539 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001540 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001541 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001542 #if GR_COLLECT_STATS
1543 ++fStats.fRenderTargetChngCnt;
1544 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001545 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001546 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1547 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001548 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001549 }
1550 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001551 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001552 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001553 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001554 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001555 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001556 fHWBounds.fViewportRect = vp;
1557 }
1558 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001559 if (NULL == bound || !bound->isEmpty()) {
1560 rt->flagAsNeedingResolve(bound);
1561 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001562}
1563
twiz@google.com0f31ca72011-03-18 17:38:11 +00001564GrGLenum gPrimitiveType2GLMode[] = {
1565 GR_GL_TRIANGLES,
1566 GR_GL_TRIANGLE_STRIP,
1567 GR_GL_TRIANGLE_FAN,
1568 GR_GL_POINTS,
1569 GR_GL_LINES,
1570 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001571};
1572
bsalomon@google.comd302f142011-03-03 13:54:13 +00001573#define SWAP_PER_DRAW 0
1574
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001575#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001576 #if GR_MAC_BUILD
1577 #include <AGL/agl.h>
1578 #elif GR_WIN32_BUILD
1579 void SwapBuf() {
1580 DWORD procID = GetCurrentProcessId();
1581 HWND hwnd = GetTopWindow(GetDesktopWindow());
1582 while(hwnd) {
1583 DWORD wndProcID = 0;
1584 GetWindowThreadProcessId(hwnd, &wndProcID);
1585 if(wndProcID == procID) {
1586 SwapBuffers(GetDC(hwnd));
1587 }
1588 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1589 }
1590 }
1591 #endif
1592#endif
1593
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001594void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type,
1595 uint32_t startVertex,
1596 uint32_t startIndex,
1597 uint32_t vertexCount,
1598 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001599 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1600
twiz@google.com0f31ca72011-03-18 17:38:11 +00001601 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001602
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001603 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1604 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1605
1606 // our setupGeometry better have adjusted this to zero since
1607 // DrawElements always draws from the begining of the arrays for idx 0.
1608 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001609
1610 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001611 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001612#if SWAP_PER_DRAW
1613 glFlush();
1614 #if GR_MAC_BUILD
1615 aglSwapBuffers(aglGetCurrentContext());
1616 int set_a_break_pt_here = 9;
1617 aglSwapBuffers(aglGetCurrentContext());
1618 #elif GR_WIN32_BUILD
1619 SwapBuf();
1620 int set_a_break_pt_here = 9;
1621 SwapBuf();
1622 #endif
1623#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001624}
1625
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001626void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
1627 uint32_t startVertex,
1628 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001629 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1630
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001631 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1632
1633 // our setupGeometry better have adjusted this to zero.
1634 // DrawElements doesn't take an offset so we always adjus the startVertex.
1635 GrAssert(0 == startVertex);
1636
1637 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1638 // account for startVertex in the DrawElements case. So we always
1639 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001640 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001641#if SWAP_PER_DRAW
1642 glFlush();
1643 #if GR_MAC_BUILD
1644 aglSwapBuffers(aglGetCurrentContext());
1645 int set_a_break_pt_here = 9;
1646 aglSwapBuffers(aglGetCurrentContext());
1647 #elif GR_WIN32_BUILD
1648 SwapBuf();
1649 int set_a_break_pt_here = 9;
1650 SwapBuf();
1651 #endif
1652#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001653}
1654
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001655void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001656
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001657 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001658 GrAssert(kNone_MSFBO != fMSFBOType);
1659 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001660 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001661 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001662 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001663 rt->textureFBOID()));
1664 #if GR_COLLECT_STATS
1665 ++fStats.fRenderTargetChngCnt;
1666 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001667 // make sure we go through flushRenderTarget() since we've modified
1668 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001669 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001670 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001671 const GrIRect dirtyRect = rt->getResolveRect();
1672 GrGLIRect r;
1673 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1674 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001675
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001676 if (kAppleES_MSFBO == fMSFBOType) {
1677 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001678 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001679 GR_GL(Scissor(r.fLeft, r.fBottom,
1680 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001681 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001682 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001683 fHWBounds.fScissorEnabled = true;
1684 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001685 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001686 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001687 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1688 flushScissor(NULL);
1689 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001690 int right = r.fLeft + r.fWidth;
1691 int top = r.fBottom + r.fHeight;
1692 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1693 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001694 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001695 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001696 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001697 }
1698}
1699
twiz@google.com0f31ca72011-03-18 17:38:11 +00001700static const GrGLenum grToGLStencilFunc[] = {
1701 GR_GL_ALWAYS, // kAlways_StencilFunc
1702 GR_GL_NEVER, // kNever_StencilFunc
1703 GR_GL_GREATER, // kGreater_StencilFunc
1704 GR_GL_GEQUAL, // kGEqual_StencilFunc
1705 GR_GL_LESS, // kLess_StencilFunc
1706 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1707 GR_GL_EQUAL, // kEqual_StencilFunc,
1708 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001709};
1710GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1711GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1712GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1713GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1714GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1715GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1716GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1717GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1718GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1719
twiz@google.com0f31ca72011-03-18 17:38:11 +00001720static const GrGLenum grToGLStencilOp[] = {
1721 GR_GL_KEEP, // kKeep_StencilOp
1722 GR_GL_REPLACE, // kReplace_StencilOp
1723 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1724 GR_GL_INCR, // kIncClamp_StencilOp
1725 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1726 GR_GL_DECR, // kDecClamp_StencilOp
1727 GR_GL_ZERO, // kZero_StencilOp
1728 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001729};
1730GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1731GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1732GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1733GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1734GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1735GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1736GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1737GR_STATIC_ASSERT(6 == kZero_StencilOp);
1738GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1739
reed@google.comac10a2d2010-12-22 21:39:39 +00001740void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001741 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001742
1743 // use stencil for clipping if clipping is enabled and the clip
1744 // has been written into the stencil.
1745 bool stencilClip = fClipState.fClipInStencil &&
1746 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001747 bool stencilChange = fHWStencilClip != stencilClip ||
1748 fHWDrawState.fStencilSettings != *settings ||
1749 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1750 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001751
1752 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001753
bsalomon@google.comd302f142011-03-03 13:54:13 +00001754 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1755 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001756
bsalomon@google.comd302f142011-03-03 13:54:13 +00001757 if (settings->isDisabled()) {
1758 if (stencilClip) {
1759 settings = &gClipStencilSettings;
1760 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001761 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001762
1763 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001764 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001765 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001766 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001767 #if GR_DEBUG
1768 if (!fStencilWrapOpsSupport) {
1769 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1770 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1771 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1772 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1773 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1774 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1775 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1776 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1777 }
1778 #endif
1779 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1780 GrAssert(stencilBits ||
1781 (GrStencilSettings::gDisabled ==
1782 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001783 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1784 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001785
1786 unsigned int frontRef = settings->fFrontFuncRef;
1787 unsigned int frontMask = settings->fFrontFuncMask;
1788 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001789 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001790
1791 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1792
1793 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1794 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1795 } else {
1796 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1797
1798 ConvertStencilFuncAndMask(settings->fFrontFunc,
1799 stencilClip,
1800 clipStencilMask,
1801 userStencilMask,
1802 &frontRef,
1803 &frontMask);
1804 frontWriteMask &= userStencilMask;
1805 }
1806 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001807 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001808 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001809 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001810 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001811 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001812 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001813 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001814 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001815 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001816
1817 unsigned int backRef = settings->fBackFuncRef;
1818 unsigned int backMask = settings->fBackFuncMask;
1819 unsigned int backWriteMask = settings->fBackWriteMask;
1820
1821
1822 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1823 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1824 backFunc = grToGLStencilFunc[settings->fBackFunc];
1825 } else {
1826 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1827 ConvertStencilFuncAndMask(settings->fBackFunc,
1828 stencilClip,
1829 clipStencilMask,
1830 userStencilMask,
1831 &backRef,
1832 &backMask);
1833 backWriteMask &= userStencilMask;
1834 }
1835
twiz@google.com0f31ca72011-03-18 17:38:11 +00001836 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1837 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1838 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1839 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1840 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001841 grToGLStencilOp[settings->fFrontPassOp],
1842 grToGLStencilOp[settings->fFrontPassOp]));
1843
twiz@google.com0f31ca72011-03-18 17:38:11 +00001844 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001845 grToGLStencilOp[settings->fBackPassOp],
1846 grToGLStencilOp[settings->fBackPassOp]));
1847 } else {
1848 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1849 GR_GL(StencilMask(frontWriteMask));
1850 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1851 grToGLStencilOp[settings->fFrontPassOp],
1852 grToGLStencilOp[settings->fFrontPassOp]));
1853 }
1854 }
1855 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001856 fHWStencilClip = stencilClip;
1857 }
1858}
1859
bsalomon@google.com0650e812011-04-08 18:07:53 +00001860bool GrGpuGL::useSmoothLines() {
1861 // there is a conflict between using smooth lines and our use of
1862 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1863 // but not in a premul-alpha way. So we only use them when our alpha
1864 // is 0xff.
1865
1866 // TODO: write a smarter line frag shader.
1867
1868 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1869 canDisableBlend();
1870}
1871
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001872void GrGpuGL::flushAAState(GrPrimitiveType type) {
1873 if (GR_GL_SUPPORT_DESKTOP) {
1874 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1875 // smooth lines.
1876
1877 // we prefer smooth lines over multisampled lines
1878 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001879 if (GrIsPrimTypeLines(type)) {
1880 bool smooth = useSmoothLines();
1881 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001882 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1883 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001884 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001885 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1886 fHWAAState.fSmoothLineEnabled = false;
1887 }
1888 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1889 fHWAAState.fMSAAEnabled) {
1890 GR_GL(Disable(GR_GL_MULTISAMPLE));
1891 fHWAAState.fMSAAEnabled = false;
1892 }
1893 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1894 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1895 fHWAAState.fMSAAEnabled) {
1896 if (fHWAAState.fMSAAEnabled) {
1897 GR_GL(Disable(GR_GL_MULTISAMPLE));
1898 fHWAAState.fMSAAEnabled = false;
1899 } else {
1900 GR_GL(Enable(GR_GL_MULTISAMPLE));
1901 fHWAAState.fMSAAEnabled = true;
1902 }
1903 }
1904 }
1905}
1906
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001907void GrGpuGL::flushBlend(GrPrimitiveType type,
1908 GrBlendCoeff srcCoeff,
1909 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001910 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1911 if (fHWBlendDisabled) {
1912 GR_GL(Enable(GR_GL_BLEND));
1913 fHWBlendDisabled = false;
1914 }
1915 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1916 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1917 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1918 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1919 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1920 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1921 }
1922 } else {
1923 bool blendOff = canDisableBlend();
1924 if (fHWBlendDisabled != blendOff) {
1925 if (blendOff) {
1926 GR_GL(Disable(GR_GL_BLEND));
1927 } else {
1928 GR_GL(Enable(GR_GL_BLEND));
1929 }
1930 fHWBlendDisabled = blendOff;
1931 }
1932 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001933 if (fHWDrawState.fSrcBlend != srcCoeff ||
1934 fHWDrawState.fDstBlend != dstCoeff) {
1935 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1936 gXfermodeCoeff2Blend[dstCoeff]));
1937 fHWDrawState.fSrcBlend = srcCoeff;
1938 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001939 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001940 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1941 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001942 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1943
1944 float c[] = {
1945 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1946 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1947 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1948 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1949 };
1950 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1951 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1952 }
1953 }
1954 }
1955}
1956
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +00001957static unsigned grToGLFilter(GrSamplerState::Filter filter) {
1958 switch (filter) {
1959 case GrSamplerState::kBilinear_Filter:
1960 case GrSamplerState::k4x4Downsample_Filter:
1961 return GR_GL_LINEAR;
1962 case GrSamplerState::kNearest_Filter:
1963 case GrSamplerState::kConvolution_Filter:
1964 return GR_GL_NEAREST;
1965 default:
1966 GrAssert(!"Unknown filter type");
1967 return GR_GL_LINEAR;
1968 }
1969}
1970
bsalomon@google.comffca4002011-02-22 20:34:01 +00001971bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001972
1973 // GrGpu::setupClipAndFlushState should have already checked this
1974 // and bailed if not true.
1975 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001976
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001977 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001978 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001979 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001980 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001981
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001982 // true for now, but maybe not with GrEffect.
1983 GrAssert(NULL != nextTexture);
1984 // if we created a rt/tex and rendered to it without using a
1985 // texture and now we're texuring from the rt it will still be
1986 // the last bound texture, but it needs resolving. So keep this
1987 // out of the "last != next" check.
1988 GrGLRenderTarget* texRT =
1989 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1990 if (NULL != texRT) {
1991 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001992 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001993
1994 if (fHWDrawState.fTextures[s] != nextTexture) {
1995 setTextureUnit(s);
1996 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1997 #if GR_COLLECT_STATS
1998 ++fStats.fTextureChngCnt;
1999 #endif
2000 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
2001 fHWDrawState.fTextures[s] = nextTexture;
bsalomon@google.comcd19a5f2011-06-15 14:00:23 +00002002 // The texture matrix has to compensate for texture width/height
2003 // and NPOT-embedded-in-POT
2004 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00002005 }
2006
2007 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
2008 const GrGLTexture::TexParams& oldTexParams =
2009 nextTexture->getTexParams();
2010 GrGLTexture::TexParams newTexParams;
2011
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +00002012 newTexParams.fFilter = grToGLFilter(sampler.getFilter());
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00002013
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00002014 newTexParams.fWrapS =
2015 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
2016 newTexParams.fWrapT =
2017 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
2018
2019 if (newTexParams.fFilter != oldTexParams.fFilter) {
2020 setTextureUnit(s);
2021 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
2022 GR_GL_TEXTURE_MAG_FILTER,
2023 newTexParams.fFilter));
2024 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
2025 GR_GL_TEXTURE_MIN_FILTER,
2026 newTexParams.fFilter));
2027 }
2028 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
2029 setTextureUnit(s);
2030 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
2031 GR_GL_TEXTURE_WRAP_S,
2032 newTexParams.fWrapS));
2033 }
2034 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
2035 setTextureUnit(s);
2036 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
2037 GR_GL_TEXTURE_WRAP_T,
2038 newTexParams.fWrapT));
2039 }
2040 nextTexture->setTexParams(newTexParams);
reed@google.comac10a2d2010-12-22 21:39:39 +00002041 }
2042 }
2043
bsalomon@google.com8295dc12011-05-02 12:53:34 +00002044 GrIRect* rect = NULL;
2045 GrIRect clipBounds;
2046 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
2047 fClip.hasConservativeBounds()) {
2048 fClip.getConservativeBounds().roundOut(&clipBounds);
2049 rect = &clipBounds;
2050 }
2051 this->flushRenderTarget(rect);
2052 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00002053
reed@google.comac10a2d2010-12-22 21:39:39 +00002054 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
2055 (fHWDrawState.fFlagBits & kDither_StateBit)) {
2056 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002057 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00002058 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002059 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00002060 }
2061 }
2062
bsalomon@google.comd302f142011-03-03 13:54:13 +00002063 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
2064 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002065 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00002066 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002067 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00002068 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002069 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00002070 }
2071 GR_GL(ColorMask(mask, mask, mask, mask));
2072 }
2073
bsalomon@google.comd302f142011-03-03 13:54:13 +00002074 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
2075 switch (fCurrDrawState.fDrawFace) {
2076 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002077 GR_GL(Enable(GR_GL_CULL_FACE));
2078 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00002079 break;
2080 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002081 GR_GL(Enable(GR_GL_CULL_FACE));
2082 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00002083 break;
2084 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002085 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00002086 break;
2087 default:
2088 GrCrash("Unknown draw face.");
2089 }
2090 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
2091 }
2092
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002093#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00002094 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002095 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00002096 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002097 NULL == fCurrDrawState.fRenderTarget ||
2098 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00002099 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002100 fCurrDrawState.fRenderTarget);
2101 }
2102#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00002103
reed@google.comac10a2d2010-12-22 21:39:39 +00002104 flushStencil();
2105
bsalomon@google.comd302f142011-03-03 13:54:13 +00002106 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00002107 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00002108 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00002109}
2110
2111void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002112 if (fHWGeometryState.fVertexBuffer != buffer) {
2113 fHWGeometryState.fArrayPtrsDirty = true;
2114 fHWGeometryState.fVertexBuffer = buffer;
2115 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002116}
2117
2118void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002119 if (fHWGeometryState.fVertexBuffer == buffer) {
2120 // deleting bound buffer does implied bind to 0
2121 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002122 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00002123 }
2124}
2125
2126void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002127 fHWGeometryState.fIndexBuffer = buffer;
reed@google.comac10a2d2010-12-22 21:39:39 +00002128}
2129
2130void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002131 if (fHWGeometryState.fIndexBuffer == buffer) {
2132 // deleting bound buffer does implied bind to 0
2133 fHWGeometryState.fIndexBuffer = NULL;
2134 }
2135}
2136
reed@google.comac10a2d2010-12-22 21:39:39 +00002137void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
2138 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00002139 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00002140 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00002141 }
2142 if (fHWDrawState.fRenderTarget == renderTarget) {
2143 fHWDrawState.fRenderTarget = NULL;
2144 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002145}
2146
2147void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002148 for (int s = 0; s < kNumStages; ++s) {
2149 if (fCurrDrawState.fTextures[s] == texture) {
2150 fCurrDrawState.fTextures[s] = NULL;
2151 }
2152 if (fHWDrawState.fTextures[s] == texture) {
2153 // deleting bound texture does implied bind to 0
2154 fHWDrawState.fTextures[s] = NULL;
2155 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002156 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002157}
2158
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002159bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00002160 GrGLenum* internalFormat,
2161 GrGLenum* format,
2162 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002163 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002164 case kRGBA_8888_GrPixelConfig:
2165 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00002166 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002167 if (GR_GL_SUPPORT_ES) {
2168 // according to GL_EXT_texture_format_BGRA8888 the *internal*
2169 // format for a BGRA is BGRA not RGBA (as on desktop)
2170 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
2171 } else {
2172 *internalFormat = GR_GL_RGBA;
2173 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00002174 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00002175 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002176 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002177 *format = GR_GL_RGB;
2178 *internalFormat = GR_GL_RGB;
2179 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00002180 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002181 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002182 *format = GR_GL_RGBA;
2183 *internalFormat = GR_GL_RGBA;
2184 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002185 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002186 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002187 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002188 *format = GR_GL_PALETTE8_RGBA8;
2189 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00002190 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00002191 } else {
2192 return false;
2193 }
2194 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002195 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002196 *format = GR_GL_ALPHA;
2197 *internalFormat = GR_GL_ALPHA;
2198 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00002199 break;
2200 default:
2201 return false;
2202 }
2203 return true;
2204}
2205
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002206void GrGpuGL::setTextureUnit(int unit) {
2207 GrAssert(unit >= 0 && unit < kNumStages);
2208 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002209 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002210 fActiveTextureUnitIdx = unit;
2211 }
2212}
bsalomon@google.com316f99232011-01-13 21:28:12 +00002213
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002214void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002215 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2216 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002217 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
2218 }
2219}
2220
reed@google.comac10a2d2010-12-22 21:39:39 +00002221/* On ES the internalFormat and format must match for TexImage and we use
2222 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
2223 decide the internalFormat. However, on ES internalFormat for
2224 RenderBufferStorage* has to be a specific format (not a base format like
2225 GL_RGBA).
2226 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002227bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002228 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002229 case kRGBA_8888_GrPixelConfig:
2230 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002231 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002232 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00002233 return true;
2234 } else {
2235 return false;
2236 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002237 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002238 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2239 // with FBO extension desktop GL has
2240 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002241 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002242 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002243 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002244 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002245 return true;
2246 default:
2247 return false;
2248 }
2249}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002250
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002251void GrGpuGL::resetDirtyFlags() {
2252 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2253}
2254
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002255void GrGpuGL::setBuffers(bool indexed,
2256 int* extraVertexOffset,
2257 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002258
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002259 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002260
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002261 const GeometryPoolState& geoPoolState = this->getGeomPoolState();
2262
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002263 GrGLVertexBuffer* vbuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002264 switch (this->getGeomSrc().fVertexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002265 case kBuffer_GeometrySrcType:
2266 *extraVertexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002267 vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002268 break;
2269 case kArray_GeometrySrcType:
2270 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002271 this->finalizeReservedVertices();
2272 *extraVertexOffset = geoPoolState.fPoolStartVertex;
2273 vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002274 break;
2275 default:
2276 vbuf = NULL; // suppress warning
2277 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002278 }
2279
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002280 GrAssert(NULL != vbuf);
2281 GrAssert(!vbuf->isLocked());
2282 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002283 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002284 fHWGeometryState.fArrayPtrsDirty = true;
2285 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002286 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002287
2288 if (indexed) {
2289 GrAssert(NULL != extraIndexOffset);
2290
2291 GrGLIndexBuffer* ibuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002292 switch (this->getGeomSrc().fIndexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002293 case kBuffer_GeometrySrcType:
2294 *extraIndexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002295 ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002296 break;
2297 case kArray_GeometrySrcType:
2298 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002299 this->finalizeReservedIndices();
2300 *extraIndexOffset = geoPoolState.fPoolStartIndex;
2301 ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002302 break;
2303 default:
2304 ibuf = NULL; // suppress warning
2305 GrCrash("Unknown geometry src type!");
2306 }
2307
2308 GrAssert(NULL != ibuf);
2309 GrAssert(!ibuf->isLocked());
2310 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002311 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002312 fHWGeometryState.fIndexBuffer = ibuf;
2313 }
2314 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002315}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002316
2317int GrGpuGL::getMaxEdges() const {
2318 // FIXME: This is a pessimistic estimate based on how many other things
2319 // want to add uniforms. This should be centralized somewhere.
2320 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2321}
bsalomon@google.comfe676522011-06-17 18:12:21 +00002322