blob: 1f9afdcb5d8fe643d5cce7761a5b75a5659026b0 [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.comd302f142011-03-03 13:54:13 +0000577
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000578 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
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;
reed@google.comac10a2d2010-12-22 21:39:39 +0000589
590 fHWGeometryState.fIndexBuffer = NULL;
591 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000592
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000593 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000594
twiz@google.com0f31ca72011-03-18 17:38:11 +0000595 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000596 fHWDrawState.fRenderTarget = NULL;
597}
598
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000599GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
600
601 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
602 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
603 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
604 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
605
606 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
607 if (isRenderTarget) {
608 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
609 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
610 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
611 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
612 } else {
613 GrAssert(!isTexture); // this should have been filtered by GrContext
614 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
615 }
616 } else {
617 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
618 }
619 // we don't know what the RB ids are without glGets and we don't care
620 // since we aren't responsible for deleting them.
621 rtIDs.fStencilRenderbufferID = 0;
622 rtIDs.fMSColorRenderbufferID = 0;
623
624 rtIDs.fOwnIDs = false;
625 } else {
626 rtIDs.reset();
627 }
628
629 if (isTexture) {
630 GrGLTexture::GLTextureDesc texDesc;
631 GrGLenum dontCare;
632 if (!canBeTexture(desc.fConfig, &dontCare,
633 &texDesc.fUploadFormat,
634 &texDesc.fUploadType)) {
635 return NULL;
636 }
637
638 GrGLTexture::TexParams params;
639
640 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
641 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
642
bsalomon@google.com90405932011-06-17 15:56:55 +0000643 texDesc.fFormat = desc.fConfig;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000644 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
645 texDesc.fStencilBits = desc.fStencilBits;
646 texDesc.fTextureID = desc.fPlatformTexture;
647 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
648 texDesc.fOwnsID = false;
649
650 params.invalidate(); // rather than do glGets.
651
652 return new GrGLTexture(this, texDesc, rtIDs, params);
653 } else {
654 GrGLIRect viewport;
655 viewport.fLeft = 0;
656 viewport.fBottom = 0;
657 viewport.fWidth = desc.fWidth;
658 viewport.fHeight = desc.fHeight;
659
660 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
661 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
662 viewport, NULL);
663 }
664}
665
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000666GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000667
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000668 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000669
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000670 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000671 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
672 rtIDs.fMSColorRenderbufferID = 0;
673 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000674
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000675 GrGLIRect viewport;
676 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000677 GrGLuint stencilBits;
678 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000679
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000680 GrGLint samples;
681 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
682
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000683 rtIDs.fOwnIDs = false;
684
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000685 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
686 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000687}
688
bsalomon@google.com5782d712011-01-21 21:03:59 +0000689///////////////////////////////////////////////////////////////////////////////
690
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000691void GrGpuGL::setupStencilFormats() {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000692
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000693 // Build up list of legal stencil formats (though perhaps not supported on
694 // the particular gpu/driver) from most preferred to least.
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000695
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000696 // these consts are in order of most preferred to least preferred
697 // we don't bother with GL_STENCIL_INDEX1 or GL_DEPTH32F_STENCIL8
698 static const StencilFormat gS8 = {GR_GL_STENCIL_INDEX8, 8, false};
699 static const StencilFormat gS16 = {GR_GL_STENCIL_INDEX16, 16, false};
700 static const StencilFormat gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, true };
701 static const StencilFormat gS4 = {GR_GL_STENCIL_INDEX4, 4, false};
702 static const StencilFormat gS = {GR_GL_STENCIL_INDEX, gUNKNOWN_BITCOUNT, false};
703 static const StencilFormat gDS = {GR_GL_DEPTH_STENCIL, gUNKNOWN_BITCOUNT, true };
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000704
705 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000706 bool supportsPackedDS = fGLVersion >= 3.0f ||
707 this->hasExtension("GL_EXT_packed_depth_stencil") ||
708 this->hasExtension("GL_ARB_framebuffer_object");
709
710 // S1 thru S16 formats are in GL 3.0+, EXT_FBO, and ARB_FBO since we
711 // require FBO support we can expect these are legal formats and don't
712 // check. These also all support the unsized GL_STENCIL_INDEX.
713 fStencilFormats.push_back() = gS8;
714 fStencilFormats.push_back() = gS16;
715 if (supportsPackedDS) {
716 fStencilFormats.push_back() = gD24S8;
717 }
718 fStencilFormats.push_back() = gS4;
719 if (supportsPackedDS) {
720 fStencilFormats.push_back() = gDS;
721 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000722 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000723 // ES2 has STENCIL_INDEX8 without extensions.
724 // ES1 with GL_OES_framebuffer_object (which we require for ES1)
725 // introduces tokens for S1 thu S8 but there are separate extensions
726 // that make them legal (GL_OES_stencil1, ...).
727 // GL_OES_packed_depth_stencil adds DEPTH24_STENCIL8
728 // ES doesn't support using the unsized formats.
729
730 if (fGLVersion >= 2.f || this->hasExtension("GL_OES_stencil8")) {
731 fStencilFormats.push_back() = gS8;
732 }
733 //fStencilFormats.push_back() = gS16;
734 if (this->hasExtension("GL_OES_packed_depth_stencil")) {
735 fStencilFormats.push_back() = gD24S8;
736 }
737 if (this->hasExtension("GL_OES_stencil4")) {
738 fStencilFormats.push_back() = gS4;
739 }
740 // we require some stencil format.
741 GrAssert(fStencilFormats.count() > 0);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000742 }
743}
744
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000745// good to set a break-point here to know when createTexture fails
746static GrTexture* return_null_texture() {
747// GrAssert(!"null texture");
748 return NULL;
749}
750
751#if GR_DEBUG
752static size_t as_size_t(int x) {
753 return x;
754}
755#endif
756
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000757GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000758 const void* srcData,
759 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000760
761#if GR_COLLECT_STATS
762 ++fStats.fTextureCreateCnt;
763#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000764
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000765 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000766
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000767 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000768 GR_GL_NEAREST,
769 GR_GL_CLAMP_TO_EDGE,
770 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000771 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000772
reed@google.comac10a2d2010-12-22 21:39:39 +0000773 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000774 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000775
776 glDesc.fContentWidth = desc.fWidth;
777 glDesc.fContentHeight = desc.fHeight;
778 glDesc.fAllocWidth = desc.fWidth;
779 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000780 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000781 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000782 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000783
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000784 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000785 if (!canBeTexture(desc.fFormat,
786 &internalFormat,
787 &glDesc.fUploadFormat,
788 &glDesc.fUploadType)) {
789 return return_null_texture();
790 }
791
792 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000793 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000794 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000795 GrPrintf("AA RT requested but not supported on this platform.");
796 }
797
798 GR_GL(GenTextures(1, &glDesc.fTextureID));
799 if (!glDesc.fTextureID) {
800 return return_null_texture();
801 }
802
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000803 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000804
reed@google.com5e762232011-04-04 18:15:49 +0000805 // in case we need a temporary, trimmed copy of the src pixels
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000806 SkAutoSMalloc<128 * 128> trimStorage;
reed@google.com5e762232011-04-04 18:15:49 +0000807
reed@google.comac10a2d2010-12-22 21:39:39 +0000808 /*
809 * check if our srcData has extra bytes past each row. If so, we need
810 * to trim those off here, since GL doesn't let us pass the rowBytes as
811 * a parameter to glTexImage2D
812 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000813 if (GR_GL_SUPPORT_DESKTOP) {
814 if (srcData) {
815 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
816 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000817 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000818 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000819 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
820 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000821 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000822 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000823 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000824 char* dst = (char*)trimStorage.realloc(trimSize);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000825 for (int y = 0; y < desc.fHeight; y++) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000826 memcpy(dst, src, trimRowBytes);
827 src += rowBytes;
828 dst += trimRowBytes;
829 }
830 // now point srcData to our trimmed version
831 srcData = trimStorage.get();
832 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000833 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000834
reed@google.comac10a2d2010-12-22 21:39:39 +0000835 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000836 if (!this->npotRenderTargetSupport()) {
837 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
838 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
839 }
840
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000841 glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
842 glDesc.fAllocWidth);
843 glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
844 glDesc.fAllocHeight);
845 if (glDesc.fAllocWidth > fMaxRenderTargetSize ||
846 glDesc.fAllocHeight > fMaxRenderTargetSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000847 return return_null_texture();
848 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000849 } else if (!this->npotTextureSupport()) {
850 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
851 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000852 if (glDesc.fAllocWidth > fMaxTextureSize ||
853 glDesc.fAllocHeight > fMaxTextureSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000854 return return_null_texture();
855 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000856 }
857
twiz@google.com0f31ca72011-03-18 17:38:11 +0000858 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
859 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
860 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000861 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000862 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
863 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000864 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000865 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
866 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000867 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000868 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
869 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000870 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000871
twiz@google.com0f31ca72011-03-18 17:38:11 +0000872 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000873 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000874 supports8BitPalette()) {
875 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
876 GrAssert(desc.fWidth == glDesc.fAllocWidth);
877 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000878 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000879 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000880 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000881 glDesc.fAllocWidth, glDesc.fAllocHeight,
882 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000883 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000884 } else {
885 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
886 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000887 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000888 glDesc.fAllocWidth, glDesc.fAllocHeight,
889 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000890 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000891 desc.fHeight, glDesc.fUploadFormat,
892 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000893 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000894
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000895 int extraW = glDesc.fAllocWidth - desc.fWidth;
896 int extraH = glDesc.fAllocHeight - desc.fHeight;
897 int maxTexels = extraW * extraH;
reed@google.comac10a2d2010-12-22 21:39:39 +0000898 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
899 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
900
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000901 SkAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
reed@google.comac10a2d2010-12-22 21:39:39 +0000902
903 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
904 if (extraH) {
905 uint8_t* lastRowStart = (uint8_t*) srcData +
906 (desc.fHeight - 1) * rowSize;
907 uint8_t* extraRowStart = (uint8_t*)texels.get();
908
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000909 for (int i = 0; i < extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000910 memcpy(extraRowStart, lastRowStart, rowSize);
911 extraRowStart += rowSize;
912 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000913 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000914 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
915 texels.get()));
916 }
917 if (extraW) {
918 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
919 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000920 for (int j = 0; j < desc.fHeight; ++j) {
921 for (int i = 0; i < extraW; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
923 extraTexel += glDesc.fUploadByteCount;
924 }
925 edgeTexel += rowSize;
926 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000927 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000928 desc.fHeight, glDesc.fUploadFormat,
929 glDesc.fUploadType, texels.get()));
930 }
931 if (extraW && extraH) {
932 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
933 - glDesc.fUploadByteCount;
934 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000935 for (int i = 0; i < extraW*extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000936 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
937 extraTexel += glDesc.fUploadByteCount;
938 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000939 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000940 extraW, extraH, glDesc.fUploadFormat,
941 glDesc.fUploadType, texels.get()));
942 }
943
944 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000945 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000946 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
947 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000948 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000949 }
950 }
951
952 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
953
954 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
955 rtIDs.fStencilRenderbufferID = 0;
956 rtIDs.fMSColorRenderbufferID = 0;
957 rtIDs.fRTFBOID = 0;
958 rtIDs.fTexFBOID = 0;
959 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000960 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000961
962 if (renderTarget) {
963#if GR_COLLECT_STATS
964 ++fStats.fRenderTargetCreateCnt;
965#endif
966 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000967 GrGLenum status;
968 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000969
970 // If need have both RT flag and srcData we have
971 // to invert the data before uploading because FBO
972 // will be rendered bottom up
973 GrAssert(NULL == srcData);
974 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
975
twiz@google.com59a190b2011-03-14 21:23:01 +0000976 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000977 GrAssert(rtIDs.fTexFBOID);
978
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000979 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000980 // to one and then resolve to the texture bound to the other.
981 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000982 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000983 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000984 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000985 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
986 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000987 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000988 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000989 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
990 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000991 return return_null_texture();
992 }
993 } else {
994 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
995 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000996 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000997 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000998 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000999 }
1000
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001001 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +00001002 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001003 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +00001004 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001005
twiz@google.com0f31ca72011-03-18 17:38:11 +00001006 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001007
bsalomon@google.comfe676522011-06-17 18:12:21 +00001008 int stencilFmtCnt;
bsalomon@google.comfe676522011-06-17 18:12:21 +00001009 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001010 stencilFmtCnt = fStencilFormats.count();
bsalomon@google.comfe676522011-06-17 18:12:21 +00001011 } else {
1012 stencilFmtCnt = 1; // only 1 attempt when we don't need a stencil
1013 }
1014
1015 for (int i = 0; i < stencilFmtCnt; ++i) {
1016 // we start with the last stencil format that succeeded in hopes
1017 // that we won't go through this loop more than once after the
1018 // first (painful) stencil creation.
1019 int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
1020
reed@google.comac10a2d2010-12-22 21:39:39 +00001021 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001022 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001023 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001024 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001025 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001026 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001027 samples,
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001028 fStencilFormats[sIdx].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +00001029 glDesc.fAllocWidth,
1030 glDesc.fAllocHeight));
1031 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001032 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001033 fStencilFormats[sIdx].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +00001034 glDesc.fAllocWidth,
1035 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +00001036 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001037 err = GrGLGetGLInterface()->fGetError();
1038 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001039 continue;
1040 }
1041 }
1042 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
1043 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001044 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001045 rtIDs.fMSColorRenderbufferID));
1046 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001047 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001048 samples,
1049 msColorRenderbufferFormat,
1050 glDesc.fAllocWidth,
1051 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001052 err = GrGLGetGLInterface()->fGetError();
1053 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001054 continue;
1055 }
1056 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001057 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001058
1059#if GR_COLLECT_STATS
1060 ++fStats.fRenderTargetChngCnt;
1061#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001062 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1063 GR_GL_COLOR_ATTACHMENT0,
1064 GR_GL_TEXTURE_2D,
1065 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001066 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001067 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1068 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001069 continue;
1070 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001071 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001072 #if GR_COLLECT_STATS
1073 ++fStats.fRenderTargetChngCnt;
1074 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001075 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1076 GR_GL_COLOR_ATTACHMENT0,
1077 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001078 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001079
1080 }
1081 if (rtIDs.fStencilRenderbufferID) {
1082 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001083 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1084 GR_GL_STENCIL_ATTACHMENT,
1085 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001086 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001087 // if it is a packed format bind to depth also, otherwise
1088 // we may get an unsupported fbo completeness result
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001089 if (fStencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001090 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1091 GR_GL_DEPTH_ATTACHMENT,
1092 GR_GL_RENDERBUFFER,
1093 rtIDs.fStencilRenderbufferID));
1094 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001095 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001096 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001097
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001098 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001099 // undo the depth bind
1100 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001101 fStencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001102 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1103 GR_GL_DEPTH_ATTACHMENT,
1104 GR_GL_RENDERBUFFER,
1105 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001106 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001107 continue;
1108 }
1109 // we're successful!
1110 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001111 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comfe676522011-06-17 18:12:21 +00001112 fLastSuccessfulStencilFmtIdx = sIdx;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001113 if (gUNKNOWN_BITCOUNT == fStencilFormats[sIdx].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001114 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001115 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001116 glDesc.fStencilBits = fStencilFormats[sIdx].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001117 }
1118 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001119 break;
1120 }
1121 if (failed) {
1122 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001123 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001124 }
1125 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001126 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001127 }
1128 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001129 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001130 }
1131 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001132 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001133 }
1134 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1135 return return_null_texture();
1136 }
1137 }
1138#ifdef TRACE_TEXTURE_CREATION
1139 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1140 tex->fTextureID, width, height, tex->fUploadByteCount);
1141#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001142 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001143
1144 if (0 != rtIDs.fTexFBOID) {
1145 GrRenderTarget* rt = tex->asRenderTarget();
1146 // We've messed with FBO state but may not have set the correct viewport
1147 // so just dirty the rendertarget state to force a resend.
1148 fHWDrawState.fRenderTarget = NULL;
1149
1150 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001151 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001152 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1153 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001154 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001155 fCurrDrawState.fRenderTarget = rtSave;
1156 }
1157 }
1158 return tex;
1159}
1160
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001161GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001162 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001163 GR_GL(GenBuffers(1, &id));
1164 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001165 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001166 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001167 GrGLClearErr();
1168 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001169 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1170 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1171 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001172 GR_GL(DeleteBuffers(1, &id));
1173 // deleting bound buffer does implicit bind to 0
1174 fHWGeometryState.fVertexBuffer = NULL;
1175 return NULL;
1176 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001177 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001178 size, dynamic);
1179 fHWGeometryState.fVertexBuffer = vertexBuffer;
1180 return vertexBuffer;
1181 }
1182 return NULL;
1183}
1184
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001185GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001186 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001187 GR_GL(GenBuffers(1, &id));
1188 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001189 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001190 GrGLClearErr();
1191 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001192 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1193 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1194 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001195 GR_GL(DeleteBuffers(1, &id));
1196 // deleting bound buffer does implicit bind to 0
1197 fHWGeometryState.fIndexBuffer = NULL;
1198 return NULL;
1199 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001200 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001201 size, dynamic);
1202 fHWGeometryState.fIndexBuffer = indexBuffer;
1203 return indexBuffer;
1204 }
1205 return NULL;
1206}
1207
reed@google.comac10a2d2010-12-22 21:39:39 +00001208void GrGpuGL::flushScissor(const GrIRect* rect) {
1209 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001210 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001211 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001212
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001213 GrGLIRect scissor;
1214 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001215 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001216 rect->width(), rect->height());
1217 if (scissor.contains(vp)) {
1218 rect = NULL;
1219 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001220 }
1221
1222 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001223 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001224 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001225 fHWBounds.fScissorRect = scissor;
1226 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001227 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001228 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001229 fHWBounds.fScissorEnabled = true;
1230 }
1231 } else {
1232 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001233 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001234 fHWBounds.fScissorEnabled = false;
1235 }
1236 }
1237}
1238
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001239void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001240 if (NULL == fCurrDrawState.fRenderTarget) {
1241 return;
1242 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001243 GrIRect r;
1244 if (NULL != rect) {
1245 // flushScissor expects rect to be clipped to the target.
1246 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001247 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1248 fCurrDrawState.fRenderTarget->height());
1249 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001250 rect = &r;
1251 } else {
1252 return;
1253 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001254 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001255 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001256 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001257 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001258 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001259 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1260 GrColorUnpackG(color)/255.f,
1261 GrColorUnpackB(color)/255.f,
1262 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001263 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001264}
1265
bsalomon@google.com398109c2011-04-14 18:40:27 +00001266void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001267 if (NULL == fCurrDrawState.fRenderTarget) {
1268 return;
1269 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001270
1271 this->flushRenderTarget(&GrIRect::EmptyIRect());
1272
reed@google.comac10a2d2010-12-22 21:39:39 +00001273 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001274 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001275 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001276 }
1277 GR_GL(StencilMask(mask));
1278 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001279 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001280 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001281}
1282
bsalomon@google.com398109c2011-04-14 18:40:27 +00001283void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001284 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001285#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001286 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001287 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001288 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001289#else
1290 // we could just clear the clip bit but when we go through
1291 // angle a partial stencil mask will cause clears to be
1292 // turned into draws. Our contract on GrDrawTarget says that
1293 // changing the clip between stencil passes may or may not
1294 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001295 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001296#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001297 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001298 flushScissor(&rect);
1299 GR_GL(StencilMask(clipStencilMask));
1300 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001301 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001302 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001303}
1304
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001305void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001306 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001307}
1308
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001309bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1310 int left, int top, int width, int height,
1311 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001312 GrGLenum internalFormat; // we don't use this for glReadPixels
1313 GrGLenum format;
1314 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001315 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1316 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001317 }
1318 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1319 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1320 switch (tgt->getResolveType()) {
1321 case GrGLRenderTarget::kCantResolve_ResolveType:
1322 return false;
1323 case GrGLRenderTarget::kAutoResolves_ResolveType:
1324 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1325 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001326 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001327 break;
1328 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001329 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001330 // we don't track the state of the READ FBO ID.
1331 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1332 break;
1333 default:
1334 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001335 }
1336
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001337 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001338
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001339 // the read rect is viewport-relative
1340 GrGLIRect readRect;
1341 readRect.setRelativeTo(glvp, left, top, width, height);
1342 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001343 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001344 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001345
1346 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1347 // API presents top-to-bottom
1348 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001349 size_t stride = width * GrBytesPerPixel(config);
bsalomon@google.com3582bf92011-06-30 21:32:31 +00001350 SkAutoMalloc rowStorage(stride);
reed@google.comac10a2d2010-12-22 21:39:39 +00001351 void* tmp = rowStorage.get();
1352
1353 const int halfY = height >> 1;
1354 char* top = reinterpret_cast<char*>(buffer);
1355 char* bottom = top + (height - 1) * stride;
1356 for (int y = 0; y < halfY; y++) {
1357 memcpy(tmp, top, stride);
1358 memcpy(top, bottom, stride);
1359 memcpy(bottom, tmp, stride);
1360 top += stride;
1361 bottom -= stride;
1362 }
1363 }
1364 return true;
1365}
1366
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001367void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001368
1369 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1370
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001371 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001372 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001373 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001374 #if GR_COLLECT_STATS
1375 ++fStats.fRenderTargetChngCnt;
1376 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001377 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001378 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1379 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001380 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001381 }
1382 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001383 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001384 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001385 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001386 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001387 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001388 fHWBounds.fViewportRect = vp;
1389 }
1390 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001391 if (NULL == bound || !bound->isEmpty()) {
1392 rt->flagAsNeedingResolve(bound);
1393 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001394}
1395
twiz@google.com0f31ca72011-03-18 17:38:11 +00001396GrGLenum gPrimitiveType2GLMode[] = {
1397 GR_GL_TRIANGLES,
1398 GR_GL_TRIANGLE_STRIP,
1399 GR_GL_TRIANGLE_FAN,
1400 GR_GL_POINTS,
1401 GR_GL_LINES,
1402 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001403};
1404
bsalomon@google.comd302f142011-03-03 13:54:13 +00001405#define SWAP_PER_DRAW 0
1406
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001407#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001408 #if GR_MAC_BUILD
1409 #include <AGL/agl.h>
1410 #elif GR_WIN32_BUILD
1411 void SwapBuf() {
1412 DWORD procID = GetCurrentProcessId();
1413 HWND hwnd = GetTopWindow(GetDesktopWindow());
1414 while(hwnd) {
1415 DWORD wndProcID = 0;
1416 GetWindowThreadProcessId(hwnd, &wndProcID);
1417 if(wndProcID == procID) {
1418 SwapBuffers(GetDC(hwnd));
1419 }
1420 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1421 }
1422 }
1423 #endif
1424#endif
1425
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001426void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type,
1427 uint32_t startVertex,
1428 uint32_t startIndex,
1429 uint32_t vertexCount,
1430 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001431 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1432
twiz@google.com0f31ca72011-03-18 17:38:11 +00001433 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001434
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001435 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1436 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1437
1438 // our setupGeometry better have adjusted this to zero since
1439 // DrawElements always draws from the begining of the arrays for idx 0.
1440 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001441
1442 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001443 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001444#if SWAP_PER_DRAW
1445 glFlush();
1446 #if GR_MAC_BUILD
1447 aglSwapBuffers(aglGetCurrentContext());
1448 int set_a_break_pt_here = 9;
1449 aglSwapBuffers(aglGetCurrentContext());
1450 #elif GR_WIN32_BUILD
1451 SwapBuf();
1452 int set_a_break_pt_here = 9;
1453 SwapBuf();
1454 #endif
1455#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001456}
1457
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001458void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
1459 uint32_t startVertex,
1460 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001461 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1462
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001463 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1464
1465 // our setupGeometry better have adjusted this to zero.
1466 // DrawElements doesn't take an offset so we always adjus the startVertex.
1467 GrAssert(0 == startVertex);
1468
1469 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1470 // account for startVertex in the DrawElements case. So we always
1471 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001472 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001473#if SWAP_PER_DRAW
1474 glFlush();
1475 #if GR_MAC_BUILD
1476 aglSwapBuffers(aglGetCurrentContext());
1477 int set_a_break_pt_here = 9;
1478 aglSwapBuffers(aglGetCurrentContext());
1479 #elif GR_WIN32_BUILD
1480 SwapBuf();
1481 int set_a_break_pt_here = 9;
1482 SwapBuf();
1483 #endif
1484#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001485}
1486
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001487void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001488
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001489 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001490 GrAssert(kNone_MSFBO != fMSFBOType);
1491 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001492 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001493 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001494 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001495 rt->textureFBOID()));
1496 #if GR_COLLECT_STATS
1497 ++fStats.fRenderTargetChngCnt;
1498 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001499 // make sure we go through flushRenderTarget() since we've modified
1500 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001501 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001502 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001503 const GrIRect dirtyRect = rt->getResolveRect();
1504 GrGLIRect r;
1505 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1506 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001507
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001508 if (kAppleES_MSFBO == fMSFBOType) {
1509 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001510 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001511 GR_GL(Scissor(r.fLeft, r.fBottom,
1512 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001513 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001514 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001515 fHWBounds.fScissorEnabled = true;
1516 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001517 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001518 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001519 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1520 flushScissor(NULL);
1521 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001522 int right = r.fLeft + r.fWidth;
1523 int top = r.fBottom + r.fHeight;
1524 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1525 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001526 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001527 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001528 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001529 }
1530}
1531
twiz@google.com0f31ca72011-03-18 17:38:11 +00001532static const GrGLenum grToGLStencilFunc[] = {
1533 GR_GL_ALWAYS, // kAlways_StencilFunc
1534 GR_GL_NEVER, // kNever_StencilFunc
1535 GR_GL_GREATER, // kGreater_StencilFunc
1536 GR_GL_GEQUAL, // kGEqual_StencilFunc
1537 GR_GL_LESS, // kLess_StencilFunc
1538 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1539 GR_GL_EQUAL, // kEqual_StencilFunc,
1540 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001541};
1542GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1543GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1544GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1545GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1546GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1547GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1548GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1549GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1550GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1551
twiz@google.com0f31ca72011-03-18 17:38:11 +00001552static const GrGLenum grToGLStencilOp[] = {
1553 GR_GL_KEEP, // kKeep_StencilOp
1554 GR_GL_REPLACE, // kReplace_StencilOp
1555 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1556 GR_GL_INCR, // kIncClamp_StencilOp
1557 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1558 GR_GL_DECR, // kDecClamp_StencilOp
1559 GR_GL_ZERO, // kZero_StencilOp
1560 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001561};
1562GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1563GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1564GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1565GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1566GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1567GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1568GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1569GR_STATIC_ASSERT(6 == kZero_StencilOp);
1570GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1571
reed@google.comac10a2d2010-12-22 21:39:39 +00001572void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001573 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001574
1575 // use stencil for clipping if clipping is enabled and the clip
1576 // has been written into the stencil.
1577 bool stencilClip = fClipState.fClipInStencil &&
1578 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001579 bool stencilChange = fHWStencilClip != stencilClip ||
1580 fHWDrawState.fStencilSettings != *settings ||
1581 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1582 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001583
1584 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001585
bsalomon@google.comd302f142011-03-03 13:54:13 +00001586 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1587 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001588
bsalomon@google.comd302f142011-03-03 13:54:13 +00001589 if (settings->isDisabled()) {
1590 if (stencilClip) {
1591 settings = &gClipStencilSettings;
1592 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001593 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001594
1595 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001596 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001597 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001598 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001599 #if GR_DEBUG
1600 if (!fStencilWrapOpsSupport) {
1601 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1602 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1603 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1604 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1605 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1606 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1607 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1608 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1609 }
1610 #endif
1611 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1612 GrAssert(stencilBits ||
1613 (GrStencilSettings::gDisabled ==
1614 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001615 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1616 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001617
1618 unsigned int frontRef = settings->fFrontFuncRef;
1619 unsigned int frontMask = settings->fFrontFuncMask;
1620 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001621 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001622
1623 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1624
1625 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1626 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1627 } else {
1628 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1629
1630 ConvertStencilFuncAndMask(settings->fFrontFunc,
1631 stencilClip,
1632 clipStencilMask,
1633 userStencilMask,
1634 &frontRef,
1635 &frontMask);
1636 frontWriteMask &= userStencilMask;
1637 }
1638 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001639 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001640 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001641 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001642 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001643 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001644 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001645 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001646 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001647 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001648
1649 unsigned int backRef = settings->fBackFuncRef;
1650 unsigned int backMask = settings->fBackFuncMask;
1651 unsigned int backWriteMask = settings->fBackWriteMask;
1652
1653
1654 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1655 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1656 backFunc = grToGLStencilFunc[settings->fBackFunc];
1657 } else {
1658 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1659 ConvertStencilFuncAndMask(settings->fBackFunc,
1660 stencilClip,
1661 clipStencilMask,
1662 userStencilMask,
1663 &backRef,
1664 &backMask);
1665 backWriteMask &= userStencilMask;
1666 }
1667
twiz@google.com0f31ca72011-03-18 17:38:11 +00001668 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1669 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1670 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1671 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1672 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001673 grToGLStencilOp[settings->fFrontPassOp],
1674 grToGLStencilOp[settings->fFrontPassOp]));
1675
twiz@google.com0f31ca72011-03-18 17:38:11 +00001676 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001677 grToGLStencilOp[settings->fBackPassOp],
1678 grToGLStencilOp[settings->fBackPassOp]));
1679 } else {
1680 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1681 GR_GL(StencilMask(frontWriteMask));
1682 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1683 grToGLStencilOp[settings->fFrontPassOp],
1684 grToGLStencilOp[settings->fFrontPassOp]));
1685 }
1686 }
1687 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001688 fHWStencilClip = stencilClip;
1689 }
1690}
1691
bsalomon@google.com0650e812011-04-08 18:07:53 +00001692bool GrGpuGL::useSmoothLines() {
1693 // there is a conflict between using smooth lines and our use of
1694 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1695 // but not in a premul-alpha way. So we only use them when our alpha
1696 // is 0xff.
1697
1698 // TODO: write a smarter line frag shader.
1699
1700 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1701 canDisableBlend();
1702}
1703
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001704void GrGpuGL::flushAAState(GrPrimitiveType type) {
1705 if (GR_GL_SUPPORT_DESKTOP) {
1706 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1707 // smooth lines.
1708
1709 // we prefer smooth lines over multisampled lines
1710 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001711 if (GrIsPrimTypeLines(type)) {
1712 bool smooth = useSmoothLines();
1713 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001714 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1715 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001716 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001717 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1718 fHWAAState.fSmoothLineEnabled = false;
1719 }
1720 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1721 fHWAAState.fMSAAEnabled) {
1722 GR_GL(Disable(GR_GL_MULTISAMPLE));
1723 fHWAAState.fMSAAEnabled = false;
1724 }
1725 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1726 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1727 fHWAAState.fMSAAEnabled) {
1728 if (fHWAAState.fMSAAEnabled) {
1729 GR_GL(Disable(GR_GL_MULTISAMPLE));
1730 fHWAAState.fMSAAEnabled = false;
1731 } else {
1732 GR_GL(Enable(GR_GL_MULTISAMPLE));
1733 fHWAAState.fMSAAEnabled = true;
1734 }
1735 }
1736 }
1737}
1738
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001739void GrGpuGL::flushBlend(GrPrimitiveType type,
1740 GrBlendCoeff srcCoeff,
1741 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001742 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1743 if (fHWBlendDisabled) {
1744 GR_GL(Enable(GR_GL_BLEND));
1745 fHWBlendDisabled = false;
1746 }
1747 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1748 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1749 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1750 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1751 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1752 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1753 }
1754 } else {
1755 bool blendOff = canDisableBlend();
1756 if (fHWBlendDisabled != blendOff) {
1757 if (blendOff) {
1758 GR_GL(Disable(GR_GL_BLEND));
1759 } else {
1760 GR_GL(Enable(GR_GL_BLEND));
1761 }
1762 fHWBlendDisabled = blendOff;
1763 }
1764 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001765 if (fHWDrawState.fSrcBlend != srcCoeff ||
1766 fHWDrawState.fDstBlend != dstCoeff) {
1767 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1768 gXfermodeCoeff2Blend[dstCoeff]));
1769 fHWDrawState.fSrcBlend = srcCoeff;
1770 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001771 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001772 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1773 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001774 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1775
1776 float c[] = {
1777 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1778 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1779 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1780 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1781 };
1782 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1783 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1784 }
1785 }
1786 }
1787}
1788
bsalomon@google.comffca4002011-02-22 20:34:01 +00001789bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001790
1791 // GrGpu::setupClipAndFlushState should have already checked this
1792 // and bailed if not true.
1793 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001794
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001795 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001796 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001797 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001798 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001799
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001800 // true for now, but maybe not with GrEffect.
1801 GrAssert(NULL != nextTexture);
1802 // if we created a rt/tex and rendered to it without using a
1803 // texture and now we're texuring from the rt it will still be
1804 // the last bound texture, but it needs resolving. So keep this
1805 // out of the "last != next" check.
1806 GrGLRenderTarget* texRT =
1807 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1808 if (NULL != texRT) {
1809 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001810 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001811
1812 if (fHWDrawState.fTextures[s] != nextTexture) {
1813 setTextureUnit(s);
1814 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1815 #if GR_COLLECT_STATS
1816 ++fStats.fTextureChngCnt;
1817 #endif
1818 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1819 fHWDrawState.fTextures[s] = nextTexture;
bsalomon@google.comcd19a5f2011-06-15 14:00:23 +00001820 // The texture matrix has to compensate for texture width/height
1821 // and NPOT-embedded-in-POT
1822 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001823 }
1824
1825 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1826 const GrGLTexture::TexParams& oldTexParams =
1827 nextTexture->getTexParams();
1828 GrGLTexture::TexParams newTexParams;
1829
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001830 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1831 newTexParams.fFilter = GR_GL_NEAREST;
1832 } else {
1833 newTexParams.fFilter = GR_GL_LINEAR;
1834 }
1835
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001836 newTexParams.fWrapS =
1837 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1838 newTexParams.fWrapT =
1839 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1840
1841 if (newTexParams.fFilter != oldTexParams.fFilter) {
1842 setTextureUnit(s);
1843 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1844 GR_GL_TEXTURE_MAG_FILTER,
1845 newTexParams.fFilter));
1846 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1847 GR_GL_TEXTURE_MIN_FILTER,
1848 newTexParams.fFilter));
1849 }
1850 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1851 setTextureUnit(s);
1852 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1853 GR_GL_TEXTURE_WRAP_S,
1854 newTexParams.fWrapS));
1855 }
1856 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1857 setTextureUnit(s);
1858 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1859 GR_GL_TEXTURE_WRAP_T,
1860 newTexParams.fWrapT));
1861 }
1862 nextTexture->setTexParams(newTexParams);
reed@google.comac10a2d2010-12-22 21:39:39 +00001863 }
1864 }
1865
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001866 GrIRect* rect = NULL;
1867 GrIRect clipBounds;
1868 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1869 fClip.hasConservativeBounds()) {
1870 fClip.getConservativeBounds().roundOut(&clipBounds);
1871 rect = &clipBounds;
1872 }
1873 this->flushRenderTarget(rect);
1874 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001875
reed@google.comac10a2d2010-12-22 21:39:39 +00001876 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1877 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1878 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001879 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001880 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001881 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001882 }
1883 }
1884
bsalomon@google.comd302f142011-03-03 13:54:13 +00001885 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1886 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001887 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001888 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001889 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001890 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001891 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001892 }
1893 GR_GL(ColorMask(mask, mask, mask, mask));
1894 }
1895
bsalomon@google.comd302f142011-03-03 13:54:13 +00001896 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1897 switch (fCurrDrawState.fDrawFace) {
1898 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001899 GR_GL(Enable(GR_GL_CULL_FACE));
1900 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001901 break;
1902 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001903 GR_GL(Enable(GR_GL_CULL_FACE));
1904 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001905 break;
1906 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001907 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001908 break;
1909 default:
1910 GrCrash("Unknown draw face.");
1911 }
1912 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1913 }
1914
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001915#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001916 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001917 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001918 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001919 NULL == fCurrDrawState.fRenderTarget ||
1920 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001921 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001922 fCurrDrawState.fRenderTarget);
1923 }
1924#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001925
reed@google.comac10a2d2010-12-22 21:39:39 +00001926 flushStencil();
1927
bsalomon@google.comd302f142011-03-03 13:54:13 +00001928 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001929 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001930 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001931}
1932
1933void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001934 if (fHWGeometryState.fVertexBuffer != buffer) {
1935 fHWGeometryState.fArrayPtrsDirty = true;
1936 fHWGeometryState.fVertexBuffer = buffer;
1937 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001938}
1939
1940void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001941 if (fHWGeometryState.fVertexBuffer == buffer) {
1942 // deleting bound buffer does implied bind to 0
1943 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001944 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001945 }
1946}
1947
1948void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001949 fHWGeometryState.fIndexBuffer = buffer;
reed@google.comac10a2d2010-12-22 21:39:39 +00001950}
1951
1952void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001953 if (fHWGeometryState.fIndexBuffer == buffer) {
1954 // deleting bound buffer does implied bind to 0
1955 fHWGeometryState.fIndexBuffer = NULL;
1956 }
1957}
1958
reed@google.comac10a2d2010-12-22 21:39:39 +00001959void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1960 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001961 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001962 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001963 }
1964 if (fHWDrawState.fRenderTarget == renderTarget) {
1965 fHWDrawState.fRenderTarget = NULL;
1966 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001967}
1968
1969void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001970 for (int s = 0; s < kNumStages; ++s) {
1971 if (fCurrDrawState.fTextures[s] == texture) {
1972 fCurrDrawState.fTextures[s] = NULL;
1973 }
1974 if (fHWDrawState.fTextures[s] == texture) {
1975 // deleting bound texture does implied bind to 0
1976 fHWDrawState.fTextures[s] = NULL;
1977 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001978 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001979}
1980
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001981bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001982 GrGLenum* internalFormat,
1983 GrGLenum* format,
1984 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001985 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001986 case kRGBA_8888_GrPixelConfig:
1987 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001988 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001989 if (GR_GL_SUPPORT_ES) {
1990 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1991 // format for a BGRA is BGRA not RGBA (as on desktop)
1992 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1993 } else {
1994 *internalFormat = GR_GL_RGBA;
1995 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001996 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001997 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001998 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001999 *format = GR_GL_RGB;
2000 *internalFormat = GR_GL_RGB;
2001 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00002002 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002003 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002004 *format = GR_GL_RGBA;
2005 *internalFormat = GR_GL_RGBA;
2006 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002007 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002008 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002009 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002010 *format = GR_GL_PALETTE8_RGBA8;
2011 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00002012 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00002013 } else {
2014 return false;
2015 }
2016 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002017 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002018 *format = GR_GL_ALPHA;
2019 *internalFormat = GR_GL_ALPHA;
2020 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00002021 break;
2022 default:
2023 return false;
2024 }
2025 return true;
2026}
2027
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002028void GrGpuGL::setTextureUnit(int unit) {
2029 GrAssert(unit >= 0 && unit < kNumStages);
2030 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002031 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002032 fActiveTextureUnitIdx = unit;
2033 }
2034}
bsalomon@google.com316f99232011-01-13 21:28:12 +00002035
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002036void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002037 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2038 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002039 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
2040 }
2041}
2042
reed@google.comac10a2d2010-12-22 21:39:39 +00002043/* On ES the internalFormat and format must match for TexImage and we use
2044 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
2045 decide the internalFormat. However, on ES internalFormat for
2046 RenderBufferStorage* has to be a specific format (not a base format like
2047 GL_RGBA).
2048 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002049bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002050 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002051 case kRGBA_8888_GrPixelConfig:
2052 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002053 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002054 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00002055 return true;
2056 } else {
2057 return false;
2058 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002059 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002060 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2061 // with FBO extension desktop GL has
2062 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002063 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002064 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002065 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002066 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002067 return true;
2068 default:
2069 return false;
2070 }
2071}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002072
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002073void GrGpuGL::resetDirtyFlags() {
2074 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2075}
2076
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002077void GrGpuGL::setBuffers(bool indexed,
2078 int* extraVertexOffset,
2079 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002080
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002081 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002082
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002083 const GeometryPoolState& geoPoolState = this->getGeomPoolState();
2084
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002085 GrGLVertexBuffer* vbuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002086 switch (this->getGeomSrc().fVertexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002087 case kBuffer_GeometrySrcType:
2088 *extraVertexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002089 vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002090 break;
2091 case kArray_GeometrySrcType:
2092 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002093 this->finalizeReservedVertices();
2094 *extraVertexOffset = geoPoolState.fPoolStartVertex;
2095 vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002096 break;
2097 default:
2098 vbuf = NULL; // suppress warning
2099 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002100 }
2101
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002102 GrAssert(NULL != vbuf);
2103 GrAssert(!vbuf->isLocked());
2104 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002105 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002106 fHWGeometryState.fArrayPtrsDirty = true;
2107 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002108 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002109
2110 if (indexed) {
2111 GrAssert(NULL != extraIndexOffset);
2112
2113 GrGLIndexBuffer* ibuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002114 switch (this->getGeomSrc().fIndexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002115 case kBuffer_GeometrySrcType:
2116 *extraIndexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002117 ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002118 break;
2119 case kArray_GeometrySrcType:
2120 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002121 this->finalizeReservedIndices();
2122 *extraIndexOffset = geoPoolState.fPoolStartIndex;
2123 ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002124 break;
2125 default:
2126 ibuf = NULL; // suppress warning
2127 GrCrash("Unknown geometry src type!");
2128 }
2129
2130 GrAssert(NULL != ibuf);
2131 GrAssert(!ibuf->isLocked());
2132 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002133 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002134 fHWGeometryState.fIndexBuffer = ibuf;
2135 }
2136 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002137}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002138
2139int GrGpuGL::getMaxEdges() const {
2140 // FIXME: This is a pessimistic estimate based on how many other things
2141 // want to add uniforms. This should be centralized somewhere.
2142 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2143}
bsalomon@google.comfe676522011-06-17 18:12:21 +00002144