blob: 09b337c362dbc0cef6150456c0559a1bfa391044 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
bsalomon@google.com1da07462011-03-10 14:51:57 +00002 Copyright 2011 Google Inc.
reed@google.comac10a2d2010-12-22 21:39:39 +00003
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17#include "GrGpuGL.h"
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +000018#include "GrTypes.h"
bsalomon@google.com3582bf92011-06-30 21:32:31 +000019#include "SkTemplates.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000020
twiz@google.com0f31ca72011-03-18 17:38:11 +000021static const GrGLuint GR_MAX_GLUINT = ~0;
22static const GrGLint GR_INVAL_GLINT = ~0;
reed@google.comac10a2d2010-12-22 21:39:39 +000023
bsalomon@google.com316f99232011-01-13 21:28:12 +000024// we use a spare texture unit to avoid
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000025// mucking with the state of any of the stages.
bsalomon@google.com316f99232011-01-13 21:28:12 +000026static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000027
reed@google.comac10a2d2010-12-22 21:39:39 +000028#define SKIP_CACHE_CHECK true
29
twiz@google.com0f31ca72011-03-18 17:38:11 +000030static const GrGLenum gXfermodeCoeff2Blend[] = {
31 GR_GL_ZERO,
32 GR_GL_ONE,
33 GR_GL_SRC_COLOR,
34 GR_GL_ONE_MINUS_SRC_COLOR,
35 GR_GL_DST_COLOR,
36 GR_GL_ONE_MINUS_DST_COLOR,
37 GR_GL_SRC_ALPHA,
38 GR_GL_ONE_MINUS_SRC_ALPHA,
39 GR_GL_DST_ALPHA,
40 GR_GL_ONE_MINUS_DST_ALPHA,
41 GR_GL_CONSTANT_COLOR,
42 GR_GL_ONE_MINUS_CONSTANT_COLOR,
43 GR_GL_CONSTANT_ALPHA,
44 GR_GL_ONE_MINUS_CONSTANT_ALPHA,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000045
46 // extended blend coeffs
47 GR_GL_SRC1_COLOR,
48 GR_GL_ONE_MINUS_SRC1_COLOR,
49 GR_GL_SRC1_ALPHA,
50 GR_GL_ONE_MINUS_SRC1_ALPHA,
reed@google.comac10a2d2010-12-22 21:39:39 +000051};
52
bsalomon@google.com271cffc2011-05-20 14:13:56 +000053bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
bsalomon@google.com080773c2011-03-15 19:09:25 +000054 static const bool gCoeffReferencesBlendConst[] = {
55 false,
56 false,
57 false,
58 false,
59 false,
60 false,
61 false,
62 false,
63 false,
64 false,
65 true,
66 true,
67 true,
68 true,
bsalomon@google.com271cffc2011-05-20 14:13:56 +000069
70 // extended blend coeffs
71 false,
72 false,
73 false,
74 false,
bsalomon@google.com080773c2011-03-15 19:09:25 +000075 };
76 return gCoeffReferencesBlendConst[coeff];
bsalomon@google.com271cffc2011-05-20 14:13:56 +000077 GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
78
79 GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
80 GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
81 GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
82 GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
83 GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
84 GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
85 GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
86 GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
87 GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
88 GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
89 GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
90 GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
91 GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
92 GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
93
94 GR_STATIC_ASSERT(14 == kS2C_BlendCoeff);
95 GR_STATIC_ASSERT(15 == kIS2C_BlendCoeff);
96 GR_STATIC_ASSERT(16 == kS2A_BlendCoeff);
97 GR_STATIC_ASSERT(17 == kIS2A_BlendCoeff);
98
99 // assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
100 GR_STATIC_ASSERT(kTotalBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
bsalomon@google.com080773c2011-03-15 19:09:25 +0000101}
102
reed@google.comac10a2d2010-12-22 21:39:39 +0000103///////////////////////////////////////////////////////////////////////////////
104
bsalomon@google.comd302f142011-03-03 13:54:13 +0000105void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
106 GrSamplerState::SampleMode mode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000107 GrMatrix* matrix) {
108 GrAssert(NULL != texture);
109 GrAssert(NULL != matrix);
110 if (GR_Scalar1 != texture->contentScaleX() ||
111 GR_Scalar1 != texture->contentScaleY()) {
112 if (GrSamplerState::kRadial_SampleMode == mode) {
113 GrMatrix scale;
114 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
115 matrix->postConcat(scale);
116 } else if (GrSamplerState::kNormal_SampleMode == mode) {
117 GrMatrix scale;
118 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
119 matrix->postConcat(scale);
120 } else {
121 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
122 }
123 }
124 GrGLTexture::Orientation orientation = texture->orientation();
125 if (GrGLTexture::kBottomUp_Orientation == orientation) {
126 GrMatrix invY;
127 invY.setAll(GR_Scalar1, 0, 0,
128 0, -GR_Scalar1, GR_Scalar1,
129 0, 0, GrMatrix::I()[8]);
130 matrix->postConcat(invY);
131 } else {
132 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
133 }
134}
135
bsalomon@google.comd302f142011-03-03 13:54:13 +0000136bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000137 const GrSamplerState& sampler) {
138 GrAssert(NULL != texture);
139 if (!sampler.getMatrix().isIdentity()) {
140 return false;
141 }
142 if (GR_Scalar1 != texture->contentScaleX() ||
143 GR_Scalar1 != texture->contentScaleY()) {
144 return false;
145 }
146 GrGLTexture::Orientation orientation = texture->orientation();
147 if (GrGLTexture::kBottomUp_Orientation == orientation) {
148 return false;
149 } else {
150 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
151 }
152 return true;
153}
154
155///////////////////////////////////////////////////////////////////////////////
156
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000157static bool gPrintStartupSpew;
158
twiz@google.com59a190b2011-03-14 21:23:01 +0000159static bool fbo_test(int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000160
twiz@google.com0f31ca72011-03-18 17:38:11 +0000161 GrGLint savedFBO;
162 GrGLint savedTexUnit;
163 GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000164 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000165
twiz@google.com0f31ca72011-03-18 17:38:11 +0000166 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000167
twiz@google.com0f31ca72011-03-18 17:38:11 +0000168 GrGLuint testFBO;
twiz@google.com59a190b2011-03-14 21:23:01 +0000169 GR_GL(GenFramebuffers(1, &testFBO));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000170 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000171 GrGLuint testRTTex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000172 GR_GL(GenTextures(1, &testRTTex));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000173 GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000174 // some implementations require texture to be mip-map complete before
175 // FBO with level 0 bound as color attachment will be framebuffer complete.
twiz@google.com0f31ca72011-03-18 17:38:11 +0000176 GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
177 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
178 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
179 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000180 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000181 GR_GL_TEXTURE_2D, testRTTex, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000182 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000183 GR_GL(DeleteFramebuffers(1, &testFBO));
reed@google.comac10a2d2010-12-22 21:39:39 +0000184 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000185
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000186 GR_GL(ActiveTexture(savedTexUnit));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000187 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000188
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000189 return status == GR_GL_FRAMEBUFFER_COMPLETE;
reed@google.comac10a2d2010-12-22 21:39:39 +0000190}
191
tomhudson@google.com747bf292011-06-14 18:16:52 +0000192static bool probe_for_npot_render_target_support(bool hasNPOTTextureSupport) {
193
194 /* Experimentation has found that some GLs that support NPOT textures
195 do not support FBOs with a NPOT texture. They report "unsupported" FBO
196 status. I don't know how to explicitly query for this. Do an
197 experiment. Note they may support NPOT with a renderbuffer but not a
198 texture. Presumably, the implementation bloats the renderbuffer
199 internally to the next POT.
200 */
201 if (hasNPOTTextureSupport) {
202 return fbo_test(200, 200);
203 }
204 return false;
205}
206
207static int probe_for_min_render_target_height(bool hasNPOTRenderTargetSupport,
208 int maxRenderTargetSize) {
209 /* The iPhone 4 has a restriction that for an FBO with texture color
210 attachment with height <= 8 then the width must be <= height. Here
211 we look for such a limitation.
212 */
213 if (gPrintStartupSpew) {
214 GrPrintf("Small height FBO texture experiments\n");
215 }
216 int minRenderTargetHeight = GR_INVAL_GLINT;
217 for (GrGLuint i = 1; i <= 256; hasNPOTRenderTargetSupport ? ++i : i *= 2) {
218 GrGLuint w = maxRenderTargetSize;
219 GrGLuint h = i;
220 if (fbo_test(w, h)) {
221 if (gPrintStartupSpew) {
222 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
223 }
224 minRenderTargetHeight = i;
225 break;
226 } else {
227 if (gPrintStartupSpew) {
228 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
229 }
230 }
231 }
232 GrAssert(GR_INVAL_GLINT != minRenderTargetHeight);
233
234 return minRenderTargetHeight;
235}
236
237static int probe_for_min_render_target_width(bool hasNPOTRenderTargetSupport,
238 int maxRenderTargetSize) {
239
240 if (gPrintStartupSpew) {
241 GrPrintf("Small width FBO texture experiments\n");
242 }
243 int minRenderTargetWidth = GR_INVAL_GLINT;
244 for (GrGLuint i = 1; i <= 256; hasNPOTRenderTargetSupport ? i *= 2 : ++i) {
245 GrGLuint w = i;
246 GrGLuint h = maxRenderTargetSize;
247 if (fbo_test(w, h)) {
248 if (gPrintStartupSpew) {
249 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
250 }
251 minRenderTargetWidth = i;
252 break;
253 } else {
254 if (gPrintStartupSpew) {
255 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
256 }
257 }
258 }
259 GrAssert(GR_INVAL_GLINT != minRenderTargetWidth);
260
261 return minRenderTargetWidth;
262}
263
264
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000265GrGpuGL::GrGpuGL()
266 : fStencilFormats(8) {
267
268 GrGLClearErr();
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000269
reed@google.comeeeb5a02010-12-23 15:12:59 +0000270 if (gPrintStartupSpew) {
271 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
272 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000273 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000274 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000275 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000276 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000277 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000278 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000279 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000280 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000281 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000282
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000283 fGLVersion = gl_version_as_float();
284 fExtensionString = (const char*) GR_GL(GetString(GR_GL_EXTENSIONS));
reed@google.comac10a2d2010-12-22 21:39:39 +0000285
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000286 this->resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000287
twiz@google.com0f31ca72011-03-18 17:38:11 +0000288 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000289 // check FS and fixed-function texture unit limits
290 // we only use textures in the fragment stage currently.
291 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000292 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
293 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
294 GrAssert(maxTextureUnits > kNumStages);
295 }
296 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
297 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
298 GrAssert(maxTextureUnits > kNumStages);
299 }
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000300 if (GR_GL_SUPPORT_ES2) {
301 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
302 &fMaxFragmentUniformVectors);
303 } else if (GR_GL_SUPPORT_DESKTOP) {
304 GrGLint max;
305 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
306 fMaxFragmentUniformVectors = max / 4;
307 } else {
308 fMaxFragmentUniformVectors = 16;
309 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000310
reed@google.comac10a2d2010-12-22 21:39:39 +0000311 ////////////////////////////////////////////////////////////////////////////
312 // Check for supported features.
313
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000314 this->setupStencilFormats();
reed@google.comac10a2d2010-12-22 21:39:39 +0000315
twiz@google.com0f31ca72011-03-18 17:38:11 +0000316 GrGLint numFormats;
317 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000318 SkAutoSTMalloc<10, GrGLint> formats(numFormats);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000319 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000320 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000321 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000322 f8bitPaletteSupport = true;
323 break;
324 }
325 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000326
327 if (gPrintStartupSpew) {
328 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
329 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000330
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000331 GR_STATIC_ASSERT(0 == kNone_GrAALevel);
332 GR_STATIC_ASSERT(1 == kLow_GrAALevel);
333 GR_STATIC_ASSERT(2 == kMed_GrAALevel);
334 GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
reed@google.comac10a2d2010-12-22 21:39:39 +0000335
336 memset(fAASamples, 0, sizeof(fAASamples));
337 fMSFBOType = kNone_MSFBO;
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000338 if (GR_GL_SUPPORT_ES) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000339 if (this->hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000340 // chrome's extension is equivalent to the EXT msaa
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000341 // and fbo_blit extensions.
342 fMSFBOType = kDesktopEXT_MSFBO;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000343 } else if (this->hasExtension("GL_APPLE_framebuffer_multisample")) {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000344 fMSFBOType = kAppleES_MSFBO;
345 }
346 } else {
347 GrAssert(GR_GL_SUPPORT_DESKTOP);
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000348 if ((fGLVersion >= 3.f) || this->hasExtension("GL_ARB_framebuffer_object")) {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000349 fMSFBOType = kDesktopARB_MSFBO;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000350 } else if (this->hasExtension("GL_EXT_framebuffer_multisample") &&
351 this->hasExtension("GL_EXT_framebuffer_blit")) {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000352 fMSFBOType = kDesktopEXT_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000353 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000354 }
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000355 if (gPrintStartupSpew) {
356 switch (fMSFBOType) {
357 case kNone_MSFBO:
358 GrPrintf("MSAA Support: NONE\n");
359 break;
360 case kDesktopARB_MSFBO:
361 GrPrintf("MSAA Support: DESKTOP ARB.\n");
362 break;
363 case kDesktopEXT_MSFBO:
364 GrPrintf("MSAA Support: DESKTOP EXT.\n");
365 break;
366 case kAppleES_MSFBO:
367 GrPrintf("MSAA Support: APPLE ES.\n");
368 break;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000369 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000370 }
371
372 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000373 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000374 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000375 if (maxSamples > 1 ) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000376 fAASamples[kNone_GrAALevel] = 0;
377 fAASamples[kLow_GrAALevel] = GrMax(2,
378 GrFixedFloorToInt((GR_FixedHalf) *
379 maxSamples));
380 fAASamples[kMed_GrAALevel] = GrMax(2,
381 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
382 maxSamples));
383 fAASamples[kHigh_GrAALevel] = maxSamples;
reed@google.comac10a2d2010-12-22 21:39:39 +0000384 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000385 if (gPrintStartupSpew) {
386 GrPrintf("\tMax Samples: %d\n", maxSamples);
387 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000388 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +0000389 fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000390
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000391 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000392 fHasStencilWrap = (fGLVersion >= 1.4f) ||
393 this->hasExtension("GL_EXT_stencil_wrap");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000394 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000395 fHasStencilWrap = (fGLVersion >= 2.0f) || this->hasExtension("GL_OES_stencil_wrap");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000396 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000397 if (gPrintStartupSpew) {
398 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
399 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000400
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000401 if (GR_GL_SUPPORT_DESKTOP) {
402 // we could also look for GL_ATI_separate_stencil extension or
403 // GL_EXT_stencil_two_side but they use different function signatures
404 // than GL2.0+ (and than each other).
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000405 fTwoSidedStencilSupport = (fGLVersion >= 2.f);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000406 // supported on GL 1.4 and higher or by extension
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000407 fStencilWrapOpsSupport = (fGLVersion >= 1.4f) ||
408 this->hasExtension("GL_EXT_stencil_wrap");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000409 } else {
410 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
411 // an ES1 extension.
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000412 fTwoSidedStencilSupport = (fGLVersion >= 2.f);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000413 // stencil wrap support is in ES2, ES1 requires extension.
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000414 fStencilWrapOpsSupport = (fGLVersion >= 2.f) ||
415 this->hasExtension("GL_OES_stencil_wrap");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000416 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000417 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000418 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
419 (fTwoSidedStencilSupport ? "YES" : "NO"),
420 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000421 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000422
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000423 if (GR_GL_SUPPORT_DESKTOP) {
424 fRGBA8Renderbuffer = true;
425 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000426 fRGBA8Renderbuffer = this->hasExtension("GL_OES_rgb8_rgba8");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000427 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000428 if (gPrintStartupSpew) {
429 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
430 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000431
432
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000433 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000434 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000435 GrAssert(this->hasExtension("GL_EXT_texture_format_BGRA8888"));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000436 }
437 }
438
439 if (GR_GL_SUPPORT_DESKTOP) {
440 fBufferLockSupport = true; // we require VBO support and the desktop VBO
441 // extension includes glMapBuffer.
442 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000443 fBufferLockSupport = this->hasExtension("GL_OES_mapbuffer");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000444 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000445
reed@google.comeeeb5a02010-12-23 15:12:59 +0000446 if (gPrintStartupSpew) {
447 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
448 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000449
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000450 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000451 if (fGLVersion >= 2.f ||
452 this->hasExtension("GL_ARB_texture_non_power_of_two")) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000453 fNPOTTextureTileSupport = true;
454 fNPOTTextureSupport = true;
455 } else {
456 fNPOTTextureTileSupport = false;
457 fNPOTTextureSupport = false;
458 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000459 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000460 if (fGLVersion >= 2.f) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000461 fNPOTTextureSupport = true;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000462 fNPOTTextureTileSupport = this->hasExtension("GL_OES_texture_npot");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000463 } else {
464 fNPOTTextureSupport =
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000465 this->hasExtension("GL_APPLE_texture_2D_limited_npot");
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000466 fNPOTTextureTileSupport = false;
467 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000468 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000469
bsalomon@google.com205d4602011-04-25 12:43:45 +0000470 fAALineSupport = GR_GL_SUPPORT_DESKTOP;
471
reed@google.comac10a2d2010-12-22 21:39:39 +0000472 ////////////////////////////////////////////////////////////////////////////
tomhudson@google.com747bf292011-06-14 18:16:52 +0000473 // Experiments to determine limitations that can't be queried.
474 // TODO: Make these a preprocess that generate some compile time constants.
475 // TODO: probe once at startup, rather than once per context creation.
reed@google.comac10a2d2010-12-22 21:39:39 +0000476
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000477 int expectNPOTTargets = GrGLGetGLInterface()->fNPOTRenderTargetSupport;
478 if (expectNPOTTargets == kProbe_GrGLCapability) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000479 fNPOTRenderTargetSupport =
480 probe_for_npot_render_target_support(fNPOTTextureSupport);
tomhudson@google.com30e4bb62011-06-15 19:41:46 +0000481 } else {
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000482 GrAssert(expectNPOTTargets == 0 || expectNPOTTargets == 1);
483 fNPOTRenderTargetSupport = static_cast<bool>(expectNPOTTargets);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000484 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000485
bsalomon@google.com0748f212011-02-01 22:56:16 +0000486 if (gPrintStartupSpew) {
487 if (fNPOTTextureSupport) {
488 GrPrintf("NPOT textures supported\n");
489 if (fNPOTTextureTileSupport) {
490 GrPrintf("NPOT texture tiling supported\n");
491 } else {
492 GrPrintf("NPOT texture tiling NOT supported\n");
493 }
494 if (fNPOTRenderTargetSupport) {
495 GrPrintf("NPOT render targets supported\n");
496 } else {
497 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000498 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000499 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000500 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000501 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000502 }
503
bsalomon@google.com91958362011-06-13 17:58:13 +0000504 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
505 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
tomhudson@google.com747bf292011-06-14 18:16:52 +0000506 // Our render targets are always created with textures as the color
bsalomon@google.com91958362011-06-13 17:58:13 +0000507 // attachment, hence this min:
508 fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000509
tomhudson@google.com747bf292011-06-14 18:16:52 +0000510 fMinRenderTargetHeight = GrGLGetGLInterface()->fMinRenderTargetHeight;
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000511 if (fMinRenderTargetHeight == kProbe_GrGLCapability) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000512 fMinRenderTargetHeight =
513 probe_for_min_render_target_height(fNPOTRenderTargetSupport,
514 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000515 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000516
tomhudson@google.com747bf292011-06-14 18:16:52 +0000517 fMinRenderTargetWidth = GrGLGetGLInterface()->fMinRenderTargetWidth;
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000518 if (fMinRenderTargetWidth == kProbe_GrGLCapability) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000519 fMinRenderTargetWidth =
520 probe_for_min_render_target_width(fNPOTRenderTargetSupport,
521 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000522 }
tomhudson@google.com747bf292011-06-14 18:16:52 +0000523
bsalomon@google.comfe676522011-06-17 18:12:21 +0000524 fLastSuccessfulStencilFmtIdx = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000525}
526
527GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000528}
529
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000530void GrGpuGL::resetContext() {
531 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000532 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000533 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000534
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000535 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000536 GR_GL(Disable(GR_GL_DEPTH_TEST));
537 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000538
twiz@google.com0f31ca72011-03-18 17:38:11 +0000539 GR_GL(Disable(GR_GL_CULL_FACE));
540 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000541 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000542
twiz@google.com0f31ca72011-03-18 17:38:11 +0000543 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000544 if (GR_GL_SUPPORT_DESKTOP) {
545 GR_GL(Disable(GR_GL_LINE_SMOOTH));
546 GR_GL(Disable(GR_GL_POINT_SMOOTH));
547 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000548 fHWAAState.fMSAAEnabled = false;
549 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000550 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000551
twiz@google.com0f31ca72011-03-18 17:38:11 +0000552 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000553 fHWDrawState.fFlagBits = 0;
554
reed@google.comac10a2d2010-12-22 21:39:39 +0000555 // we only ever use lines in hairline mode
556 GR_GL(LineWidth(1));
557
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000558 // invalid
559 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000560
reed@google.comac10a2d2010-12-22 21:39:39 +0000561 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000562 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
563 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000564
565 fHWDrawState.fBlendConstant = 0x00000000;
566 GR_GL(BlendColor(0,0,0,0));
567
reed@google.comac10a2d2010-12-22 21:39:39 +0000568 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000569
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000570 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000571
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000572 for (int s = 0; s < kNumStages; ++s) {
573 fHWDrawState.fTextures[s] = NULL;
574 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
575 -GR_ScalarMax,
576 true);
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000577 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000578 fHWDrawState.fSamplerStates[s].setConvolutionParams(0, NULL, NULL);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000579 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000580
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000581 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000582 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000583 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000584 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000585
bsalomon@google.comd302f142011-03-03 13:54:13 +0000586 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000587 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000588 fClipState.fClipIsDirty = true;
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000589 fClipState.fClipInStencil = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000590
591 fHWGeometryState.fIndexBuffer = NULL;
592 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000593
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000594 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000595
twiz@google.com0f31ca72011-03-18 17:38:11 +0000596 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000597 fHWDrawState.fRenderTarget = NULL;
598}
599
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000600GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
601
602 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
603 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
604 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
605 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
606
607 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
608 if (isRenderTarget) {
609 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
610 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
611 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
612 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
613 } else {
614 GrAssert(!isTexture); // this should have been filtered by GrContext
615 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
616 }
617 } else {
618 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
619 }
620 // we don't know what the RB ids are without glGets and we don't care
621 // since we aren't responsible for deleting them.
622 rtIDs.fStencilRenderbufferID = 0;
623 rtIDs.fMSColorRenderbufferID = 0;
624
625 rtIDs.fOwnIDs = false;
626 } else {
627 rtIDs.reset();
628 }
629
630 if (isTexture) {
631 GrGLTexture::GLTextureDesc texDesc;
632 GrGLenum dontCare;
633 if (!canBeTexture(desc.fConfig, &dontCare,
634 &texDesc.fUploadFormat,
635 &texDesc.fUploadType)) {
636 return NULL;
637 }
638
639 GrGLTexture::TexParams params;
640
641 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
642 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
643
bsalomon@google.com90405932011-06-17 15:56:55 +0000644 texDesc.fFormat = desc.fConfig;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000645 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
646 texDesc.fStencilBits = desc.fStencilBits;
647 texDesc.fTextureID = desc.fPlatformTexture;
648 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
649 texDesc.fOwnsID = false;
650
651 params.invalidate(); // rather than do glGets.
652
653 return new GrGLTexture(this, texDesc, rtIDs, params);
654 } else {
655 GrGLIRect viewport;
656 viewport.fLeft = 0;
657 viewport.fBottom = 0;
658 viewport.fWidth = desc.fWidth;
659 viewport.fHeight = desc.fHeight;
660
661 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
662 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
663 viewport, NULL);
664 }
665}
666
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000667GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000668
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000669 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000670
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000671 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000672 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
673 rtIDs.fMSColorRenderbufferID = 0;
674 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000675
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000676 GrGLIRect viewport;
677 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000678 GrGLuint stencilBits;
679 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000680
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000681 GrGLint samples;
682 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
683
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000684 rtIDs.fOwnIDs = false;
685
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000686 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
687 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000688}
689
bsalomon@google.com5782d712011-01-21 21:03:59 +0000690///////////////////////////////////////////////////////////////////////////////
691
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000692void GrGpuGL::setupStencilFormats() {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000693
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000694 // Build up list of legal stencil formats (though perhaps not supported on
695 // the particular gpu/driver) from most preferred to least.
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000696
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000697 // these consts are in order of most preferred to least preferred
698 // we don't bother with GL_STENCIL_INDEX1 or GL_DEPTH32F_STENCIL8
699 static const StencilFormat gS8 = {GR_GL_STENCIL_INDEX8, 8, false};
700 static const StencilFormat gS16 = {GR_GL_STENCIL_INDEX16, 16, false};
701 static const StencilFormat gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, true };
702 static const StencilFormat gS4 = {GR_GL_STENCIL_INDEX4, 4, false};
703 static const StencilFormat gS = {GR_GL_STENCIL_INDEX, gUNKNOWN_BITCOUNT, false};
704 static const StencilFormat gDS = {GR_GL_DEPTH_STENCIL, gUNKNOWN_BITCOUNT, true };
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000705
706 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000707 bool supportsPackedDS = fGLVersion >= 3.0f ||
708 this->hasExtension("GL_EXT_packed_depth_stencil") ||
709 this->hasExtension("GL_ARB_framebuffer_object");
710
711 // S1 thru S16 formats are in GL 3.0+, EXT_FBO, and ARB_FBO since we
712 // require FBO support we can expect these are legal formats and don't
713 // check. These also all support the unsized GL_STENCIL_INDEX.
714 fStencilFormats.push_back() = gS8;
715 fStencilFormats.push_back() = gS16;
716 if (supportsPackedDS) {
717 fStencilFormats.push_back() = gD24S8;
718 }
719 fStencilFormats.push_back() = gS4;
720 if (supportsPackedDS) {
721 fStencilFormats.push_back() = gDS;
722 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000723 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000724 // ES2 has STENCIL_INDEX8 without extensions.
725 // ES1 with GL_OES_framebuffer_object (which we require for ES1)
726 // introduces tokens for S1 thu S8 but there are separate extensions
727 // that make them legal (GL_OES_stencil1, ...).
728 // GL_OES_packed_depth_stencil adds DEPTH24_STENCIL8
729 // ES doesn't support using the unsized formats.
730
731 if (fGLVersion >= 2.f || this->hasExtension("GL_OES_stencil8")) {
732 fStencilFormats.push_back() = gS8;
733 }
734 //fStencilFormats.push_back() = gS16;
735 if (this->hasExtension("GL_OES_packed_depth_stencil")) {
736 fStencilFormats.push_back() = gD24S8;
737 }
738 if (this->hasExtension("GL_OES_stencil4")) {
739 fStencilFormats.push_back() = gS4;
740 }
741 // we require some stencil format.
742 GrAssert(fStencilFormats.count() > 0);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000743 }
744}
745
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000746// good to set a break-point here to know when createTexture fails
747static GrTexture* return_null_texture() {
748// GrAssert(!"null texture");
749 return NULL;
750}
751
752#if GR_DEBUG
753static size_t as_size_t(int x) {
754 return x;
755}
756#endif
757
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000758GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000759 const void* srcData,
760 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000761
762#if GR_COLLECT_STATS
763 ++fStats.fTextureCreateCnt;
764#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000765
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000766 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000767
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000768 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000769 GR_GL_NEAREST,
770 GR_GL_CLAMP_TO_EDGE,
771 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000772 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000773
reed@google.comac10a2d2010-12-22 21:39:39 +0000774 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000775 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000776
777 glDesc.fContentWidth = desc.fWidth;
778 glDesc.fContentHeight = desc.fHeight;
779 glDesc.fAllocWidth = desc.fWidth;
780 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000781 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000782 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000783 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000784
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000785 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000786 if (!canBeTexture(desc.fFormat,
787 &internalFormat,
788 &glDesc.fUploadFormat,
789 &glDesc.fUploadType)) {
790 return return_null_texture();
791 }
792
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000793 // We keep GrRenderTargets in GL's normal orientation so that they
794 // can be drawn to by the outside world without the client having
795 // to render upside down.
796 glDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
797 GrGLTexture::kTopDown_Orientation;
798
reed@google.comac10a2d2010-12-22 21:39:39 +0000799 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000800 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000801 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000802 GrPrintf("AA RT requested but not supported on this platform.");
803 }
804
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000805 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000806
reed@google.com5e762232011-04-04 18:15:49 +0000807 // in case we need a temporary, trimmed copy of the src pixels
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000808 SkAutoSMalloc<128 * 128> tempStorage;
reed@google.com5e762232011-04-04 18:15:49 +0000809
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000810 if (!rowBytes) {
811 rowBytes = glDesc.fUploadByteCount * desc.fWidth;
812 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000813 /*
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000814 * check whether to allocate a temporary buffer for flipping y or
815 * because our srcData has extra bytes past each row. If so, we need
816 * to trim those off here, since GL ES doesn't let us specify
817 * GL_UNPACK_ROW_LENGTH.
reed@google.comac10a2d2010-12-22 21:39:39 +0000818 */
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000819 bool flipY = GrGLTexture::kBottomUp_Orientation == glDesc.fOrientation;
820 if (GR_GL_SUPPORT_DESKTOP && !flipY) {
821 if (srcData && rowBytes != desc.fWidth * glDesc.fUploadByteCount) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000822 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
823 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000824 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000825 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000826 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000827 if (srcData && (trimRowBytes < rowBytes || flipY)) {
reed@google.com5e762232011-04-04 18:15:49 +0000828 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000829 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000830 const char* src = (const char*)srcData;
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000831 if (flipY) {
832 src += (desc.fHeight - 1) * rowBytes;
833 }
834 char* dst = (char*)tempStorage.realloc(trimSize);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000835 for (int y = 0; y < desc.fHeight; y++) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000836 memcpy(dst, src, trimRowBytes);
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000837 if (flipY) {
838 src -= rowBytes;
839 } else {
840 src += rowBytes;
841 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000842 dst += trimRowBytes;
843 }
844 // now point srcData to our trimmed version
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000845 srcData = tempStorage.get();
846 rowBytes = trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000847 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000848 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000849
reed@google.comac10a2d2010-12-22 21:39:39 +0000850 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000851 if (!this->npotRenderTargetSupport()) {
852 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
853 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
854 }
855
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000856 glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
857 glDesc.fAllocWidth);
858 glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
859 glDesc.fAllocHeight);
860 if (glDesc.fAllocWidth > fMaxRenderTargetSize ||
861 glDesc.fAllocHeight > fMaxRenderTargetSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000862 return return_null_texture();
863 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000864 } else if (!this->npotTextureSupport()) {
865 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
866 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000867 if (glDesc.fAllocWidth > fMaxTextureSize ||
868 glDesc.fAllocHeight > fMaxTextureSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000869 return return_null_texture();
870 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000871 }
872
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000873 GR_GL(GenTextures(1, &glDesc.fTextureID));
874 if (!glDesc.fTextureID) {
875 return return_null_texture();
876 }
877
twiz@google.com0f31ca72011-03-18 17:38:11 +0000878 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
879 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
880 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000881 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000882 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
883 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000884 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000885 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
886 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000887 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000888 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
889 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000890 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000891
twiz@google.com0f31ca72011-03-18 17:38:11 +0000892 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000893 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000894 supports8BitPalette()) {
895 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
896 GrAssert(desc.fWidth == glDesc.fAllocWidth);
897 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000898 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000899 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000900 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000901 glDesc.fAllocWidth, glDesc.fAllocHeight,
902 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000903 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000904 } else {
905 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
906 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000907 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000908 glDesc.fAllocWidth, glDesc.fAllocHeight,
909 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000910 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000911 desc.fHeight, glDesc.fUploadFormat,
912 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000913 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000914
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000915 int extraW = glDesc.fAllocWidth - desc.fWidth;
916 int extraH = glDesc.fAllocHeight - desc.fHeight;
917 int maxTexels = extraW * extraH;
reed@google.comac10a2d2010-12-22 21:39:39 +0000918 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
919 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
920
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000921 SkAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
reed@google.comac10a2d2010-12-22 21:39:39 +0000922
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000923 // rowBytes is actual stride between rows in srcData
924 // rowDataBytes is the actual amount of non-pad data in a row
925 // and the stride used for uploading extraH rows.
926 uint32_t rowDataBytes = desc.fWidth * glDesc.fUploadByteCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000927 if (extraH) {
928 uint8_t* lastRowStart = (uint8_t*) srcData +
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000929 (desc.fHeight - 1) * rowBytes;
reed@google.comac10a2d2010-12-22 21:39:39 +0000930 uint8_t* extraRowStart = (uint8_t*)texels.get();
931
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000932 for (int i = 0; i < extraH; ++i) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000933 memcpy(extraRowStart, lastRowStart, rowDataBytes);
934 extraRowStart += rowDataBytes;
reed@google.comac10a2d2010-12-22 21:39:39 +0000935 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000936 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000937 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
938 texels.get()));
939 }
940 if (extraW) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000941 uint8_t* edgeTexel = (uint8_t*)srcData + rowDataBytes - glDesc.fUploadByteCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000942 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000943 for (int j = 0; j < desc.fHeight; ++j) {
944 for (int i = 0; i < extraW; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000945 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
946 extraTexel += glDesc.fUploadByteCount;
947 }
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000948 edgeTexel += rowBytes;
reed@google.comac10a2d2010-12-22 21:39:39 +0000949 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000950 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000951 desc.fHeight, glDesc.fUploadFormat,
952 glDesc.fUploadType, texels.get()));
953 }
954 if (extraW && extraH) {
bsalomon@google.comd9f826c2011-07-18 15:25:04 +0000955 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowBytes
reed@google.comac10a2d2010-12-22 21:39:39 +0000956 - glDesc.fUploadByteCount;
957 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000958 for (int i = 0; i < extraW*extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000959 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
960 extraTexel += glDesc.fUploadByteCount;
961 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000962 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000963 extraW, extraH, glDesc.fUploadFormat,
964 glDesc.fUploadType, texels.get()));
965 }
966
967 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000968 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000969 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
970 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000971 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000972 }
973 }
974
reed@google.comac10a2d2010-12-22 21:39:39 +0000975
976 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
977 rtIDs.fStencilRenderbufferID = 0;
978 rtIDs.fMSColorRenderbufferID = 0;
979 rtIDs.fRTFBOID = 0;
980 rtIDs.fTexFBOID = 0;
981 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000982 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000983
984 if (renderTarget) {
985#if GR_COLLECT_STATS
986 ++fStats.fRenderTargetCreateCnt;
987#endif
988 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000989 GrGLenum status;
990 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000991
twiz@google.com59a190b2011-03-14 21:23:01 +0000992 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000993 GrAssert(rtIDs.fTexFBOID);
994
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000995 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000996 // to one and then resolve to the texture bound to the other.
997 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000998 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000999 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +00001000 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001001 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
1002 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001003 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001004 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +00001005 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
1006 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001007 return return_null_texture();
1008 }
1009 } else {
1010 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
1011 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001012 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001013 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001014 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +00001015 }
1016
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001017 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +00001018 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001019 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +00001020 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001021
twiz@google.com0f31ca72011-03-18 17:38:11 +00001022 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001023
bsalomon@google.comfe676522011-06-17 18:12:21 +00001024 int stencilFmtCnt;
bsalomon@google.comfe676522011-06-17 18:12:21 +00001025 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001026 stencilFmtCnt = fStencilFormats.count();
bsalomon@google.comfe676522011-06-17 18:12:21 +00001027 } else {
1028 stencilFmtCnt = 1; // only 1 attempt when we don't need a stencil
1029 }
1030
1031 for (int i = 0; i < stencilFmtCnt; ++i) {
1032 // we start with the last stencil format that succeeded in hopes
1033 // that we won't go through this loop more than once after the
1034 // first (painful) stencil creation.
1035 int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
1036
reed@google.comac10a2d2010-12-22 21:39:39 +00001037 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001038 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001039 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001040 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001041 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001042 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001043 samples,
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001044 fStencilFormats[sIdx].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +00001045 glDesc.fAllocWidth,
1046 glDesc.fAllocHeight));
1047 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001048 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001049 fStencilFormats[sIdx].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +00001050 glDesc.fAllocWidth,
1051 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +00001052 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001053 err = GrGLGetGLInterface()->fGetError();
1054 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001055 continue;
1056 }
1057 }
1058 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
1059 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001060 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001061 rtIDs.fMSColorRenderbufferID));
1062 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001063 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001064 samples,
1065 msColorRenderbufferFormat,
1066 glDesc.fAllocWidth,
1067 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001068 err = GrGLGetGLInterface()->fGetError();
1069 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001070 continue;
1071 }
1072 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001073 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001074
1075#if GR_COLLECT_STATS
1076 ++fStats.fRenderTargetChngCnt;
1077#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001078 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1079 GR_GL_COLOR_ATTACHMENT0,
1080 GR_GL_TEXTURE_2D,
1081 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001082 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001083 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1084 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001085 continue;
1086 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001087 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 #if GR_COLLECT_STATS
1089 ++fStats.fRenderTargetChngCnt;
1090 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001091 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1092 GR_GL_COLOR_ATTACHMENT0,
1093 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001094 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001095
1096 }
1097 if (rtIDs.fStencilRenderbufferID) {
1098 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001099 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1100 GR_GL_STENCIL_ATTACHMENT,
1101 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001102 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001103 // if it is a packed format bind to depth also, otherwise
1104 // we may get an unsupported fbo completeness result
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001105 if (fStencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001106 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1107 GR_GL_DEPTH_ATTACHMENT,
1108 GR_GL_RENDERBUFFER,
1109 rtIDs.fStencilRenderbufferID));
1110 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001111 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001112 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001113
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001114 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001115 // undo the depth bind
1116 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001117 fStencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001118 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1119 GR_GL_DEPTH_ATTACHMENT,
1120 GR_GL_RENDERBUFFER,
1121 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001122 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001123 continue;
1124 }
1125 // we're successful!
1126 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001127 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comfe676522011-06-17 18:12:21 +00001128 fLastSuccessfulStencilFmtIdx = sIdx;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001129 if (gUNKNOWN_BITCOUNT == fStencilFormats[sIdx].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001130 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001131 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001132 glDesc.fStencilBits = fStencilFormats[sIdx].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001133 }
1134 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001135 break;
1136 }
1137 if (failed) {
1138 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001139 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001140 }
1141 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001142 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001143 }
1144 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001145 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001146 }
1147 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001148 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001149 }
1150 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1151 return return_null_texture();
1152 }
1153 }
1154#ifdef TRACE_TEXTURE_CREATION
1155 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1156 tex->fTextureID, width, height, tex->fUploadByteCount);
1157#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001158 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001159
1160 if (0 != rtIDs.fTexFBOID) {
1161 GrRenderTarget* rt = tex->asRenderTarget();
1162 // We've messed with FBO state but may not have set the correct viewport
1163 // so just dirty the rendertarget state to force a resend.
1164 fHWDrawState.fRenderTarget = NULL;
1165
1166 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001167 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001168 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1169 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001170 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001171 fCurrDrawState.fRenderTarget = rtSave;
1172 }
1173 }
1174 return tex;
1175}
1176
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001177GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001178 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001179 GR_GL(GenBuffers(1, &id));
1180 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001181 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001182 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001183 GrGLClearErr();
1184 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001185 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1186 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1187 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001188 GR_GL(DeleteBuffers(1, &id));
1189 // deleting bound buffer does implicit bind to 0
1190 fHWGeometryState.fVertexBuffer = NULL;
1191 return NULL;
1192 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001193 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001194 size, dynamic);
1195 fHWGeometryState.fVertexBuffer = vertexBuffer;
1196 return vertexBuffer;
1197 }
1198 return NULL;
1199}
1200
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001201GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001202 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001203 GR_GL(GenBuffers(1, &id));
1204 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001205 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001206 GrGLClearErr();
1207 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001208 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1209 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1210 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001211 GR_GL(DeleteBuffers(1, &id));
1212 // deleting bound buffer does implicit bind to 0
1213 fHWGeometryState.fIndexBuffer = NULL;
1214 return NULL;
1215 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001216 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001217 size, dynamic);
1218 fHWGeometryState.fIndexBuffer = indexBuffer;
1219 return indexBuffer;
1220 }
1221 return NULL;
1222}
1223
reed@google.comac10a2d2010-12-22 21:39:39 +00001224void GrGpuGL::flushScissor(const GrIRect* rect) {
1225 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001226 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001227 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001228
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001229 GrGLIRect scissor;
1230 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001231 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001232 rect->width(), rect->height());
1233 if (scissor.contains(vp)) {
1234 rect = NULL;
1235 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001236 }
1237
1238 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001239 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001240 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001241 fHWBounds.fScissorRect = scissor;
1242 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001243 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001244 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001245 fHWBounds.fScissorEnabled = true;
1246 }
1247 } else {
1248 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001249 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001250 fHWBounds.fScissorEnabled = false;
1251 }
1252 }
1253}
1254
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001255void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001256 if (NULL == fCurrDrawState.fRenderTarget) {
1257 return;
1258 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001259 GrIRect r;
1260 if (NULL != rect) {
1261 // flushScissor expects rect to be clipped to the target.
1262 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001263 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1264 fCurrDrawState.fRenderTarget->height());
1265 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001266 rect = &r;
1267 } else {
1268 return;
1269 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001270 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001271 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001272 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001273 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001274 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001275 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1276 GrColorUnpackG(color)/255.f,
1277 GrColorUnpackB(color)/255.f,
1278 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001279 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001280}
1281
bsalomon@google.com398109c2011-04-14 18:40:27 +00001282void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001283 if (NULL == fCurrDrawState.fRenderTarget) {
1284 return;
1285 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001286
1287 this->flushRenderTarget(&GrIRect::EmptyIRect());
1288
reed@google.comac10a2d2010-12-22 21:39:39 +00001289 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001290 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001291 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001292 }
1293 GR_GL(StencilMask(mask));
1294 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001295 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001296 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001297}
1298
bsalomon@google.com398109c2011-04-14 18:40:27 +00001299void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001300 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001301#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001302 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001303 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001304 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001305#else
1306 // we could just clear the clip bit but when we go through
1307 // angle a partial stencil mask will cause clears to be
1308 // turned into draws. Our contract on GrDrawTarget says that
1309 // changing the clip between stencil passes may or may not
1310 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001311 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001312#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001313 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001314 flushScissor(&rect);
1315 GR_GL(StencilMask(clipStencilMask));
1316 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001317 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001318 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001319}
1320
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001321void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001322 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001323}
1324
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001325bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1326 int left, int top, int width, int height,
1327 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001328 GrGLenum internalFormat; // we don't use this for glReadPixels
1329 GrGLenum format;
1330 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001331 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1332 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001333 }
1334 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1335 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1336 switch (tgt->getResolveType()) {
1337 case GrGLRenderTarget::kCantResolve_ResolveType:
1338 return false;
1339 case GrGLRenderTarget::kAutoResolves_ResolveType:
1340 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1341 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001342 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001343 break;
1344 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001345 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001346 // we don't track the state of the READ FBO ID.
1347 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1348 break;
1349 default:
1350 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001351 }
1352
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001353 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001354
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001355 // the read rect is viewport-relative
1356 GrGLIRect readRect;
1357 readRect.setRelativeTo(glvp, left, top, width, height);
1358 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001359 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001360 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001361
1362 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1363 // API presents top-to-bottom
1364 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001365 size_t stride = width * GrBytesPerPixel(config);
bsalomon@google.com3582bf92011-06-30 21:32:31 +00001366 SkAutoMalloc rowStorage(stride);
reed@google.comac10a2d2010-12-22 21:39:39 +00001367 void* tmp = rowStorage.get();
1368
1369 const int halfY = height >> 1;
1370 char* top = reinterpret_cast<char*>(buffer);
1371 char* bottom = top + (height - 1) * stride;
1372 for (int y = 0; y < halfY; y++) {
1373 memcpy(tmp, top, stride);
1374 memcpy(top, bottom, stride);
1375 memcpy(bottom, tmp, stride);
1376 top += stride;
1377 bottom -= stride;
1378 }
1379 }
1380 return true;
1381}
1382
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001383void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001384
1385 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1386
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001387 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001388 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001389 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001390 #if GR_COLLECT_STATS
1391 ++fStats.fRenderTargetChngCnt;
1392 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001393 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001394 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1395 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001396 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001397 }
1398 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001399 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001400 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001401 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001402 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001403 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001404 fHWBounds.fViewportRect = vp;
1405 }
1406 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001407 if (NULL == bound || !bound->isEmpty()) {
1408 rt->flagAsNeedingResolve(bound);
1409 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001410}
1411
twiz@google.com0f31ca72011-03-18 17:38:11 +00001412GrGLenum gPrimitiveType2GLMode[] = {
1413 GR_GL_TRIANGLES,
1414 GR_GL_TRIANGLE_STRIP,
1415 GR_GL_TRIANGLE_FAN,
1416 GR_GL_POINTS,
1417 GR_GL_LINES,
1418 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001419};
1420
bsalomon@google.comd302f142011-03-03 13:54:13 +00001421#define SWAP_PER_DRAW 0
1422
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001423#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001424 #if GR_MAC_BUILD
1425 #include <AGL/agl.h>
1426 #elif GR_WIN32_BUILD
1427 void SwapBuf() {
1428 DWORD procID = GetCurrentProcessId();
1429 HWND hwnd = GetTopWindow(GetDesktopWindow());
1430 while(hwnd) {
1431 DWORD wndProcID = 0;
1432 GetWindowThreadProcessId(hwnd, &wndProcID);
1433 if(wndProcID == procID) {
1434 SwapBuffers(GetDC(hwnd));
1435 }
1436 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1437 }
1438 }
1439 #endif
1440#endif
1441
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001442void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type,
1443 uint32_t startVertex,
1444 uint32_t startIndex,
1445 uint32_t vertexCount,
1446 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001447 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1448
twiz@google.com0f31ca72011-03-18 17:38:11 +00001449 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001450
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001451 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1452 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1453
1454 // our setupGeometry better have adjusted this to zero since
1455 // DrawElements always draws from the begining of the arrays for idx 0.
1456 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001457
1458 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001459 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001460#if SWAP_PER_DRAW
1461 glFlush();
1462 #if GR_MAC_BUILD
1463 aglSwapBuffers(aglGetCurrentContext());
1464 int set_a_break_pt_here = 9;
1465 aglSwapBuffers(aglGetCurrentContext());
1466 #elif GR_WIN32_BUILD
1467 SwapBuf();
1468 int set_a_break_pt_here = 9;
1469 SwapBuf();
1470 #endif
1471#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001472}
1473
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001474void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
1475 uint32_t startVertex,
1476 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001477 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1478
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001479 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1480
1481 // our setupGeometry better have adjusted this to zero.
1482 // DrawElements doesn't take an offset so we always adjus the startVertex.
1483 GrAssert(0 == startVertex);
1484
1485 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1486 // account for startVertex in the DrawElements case. So we always
1487 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001488 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001489#if SWAP_PER_DRAW
1490 glFlush();
1491 #if GR_MAC_BUILD
1492 aglSwapBuffers(aglGetCurrentContext());
1493 int set_a_break_pt_here = 9;
1494 aglSwapBuffers(aglGetCurrentContext());
1495 #elif GR_WIN32_BUILD
1496 SwapBuf();
1497 int set_a_break_pt_here = 9;
1498 SwapBuf();
1499 #endif
1500#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001501}
1502
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001503void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001504
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001505 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001506 GrAssert(kNone_MSFBO != fMSFBOType);
1507 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001508 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001509 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001510 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001511 rt->textureFBOID()));
1512 #if GR_COLLECT_STATS
1513 ++fStats.fRenderTargetChngCnt;
1514 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001515 // make sure we go through flushRenderTarget() since we've modified
1516 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001517 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001518 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001519 const GrIRect dirtyRect = rt->getResolveRect();
1520 GrGLIRect r;
1521 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1522 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001523
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001524 if (kAppleES_MSFBO == fMSFBOType) {
1525 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001526 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001527 GR_GL(Scissor(r.fLeft, r.fBottom,
1528 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001529 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001530 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001531 fHWBounds.fScissorEnabled = true;
1532 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001533 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001534 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001535 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1536 flushScissor(NULL);
1537 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001538 int right = r.fLeft + r.fWidth;
1539 int top = r.fBottom + r.fHeight;
1540 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1541 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001542 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001543 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001544 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001545 }
1546}
1547
twiz@google.com0f31ca72011-03-18 17:38:11 +00001548static const GrGLenum grToGLStencilFunc[] = {
1549 GR_GL_ALWAYS, // kAlways_StencilFunc
1550 GR_GL_NEVER, // kNever_StencilFunc
1551 GR_GL_GREATER, // kGreater_StencilFunc
1552 GR_GL_GEQUAL, // kGEqual_StencilFunc
1553 GR_GL_LESS, // kLess_StencilFunc
1554 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1555 GR_GL_EQUAL, // kEqual_StencilFunc,
1556 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001557};
1558GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1559GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1560GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1561GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1562GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1563GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1564GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1565GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1566GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1567
twiz@google.com0f31ca72011-03-18 17:38:11 +00001568static const GrGLenum grToGLStencilOp[] = {
1569 GR_GL_KEEP, // kKeep_StencilOp
1570 GR_GL_REPLACE, // kReplace_StencilOp
1571 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1572 GR_GL_INCR, // kIncClamp_StencilOp
1573 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1574 GR_GL_DECR, // kDecClamp_StencilOp
1575 GR_GL_ZERO, // kZero_StencilOp
1576 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001577};
1578GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1579GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1580GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1581GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1582GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1583GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1584GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1585GR_STATIC_ASSERT(6 == kZero_StencilOp);
1586GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1587
reed@google.comac10a2d2010-12-22 21:39:39 +00001588void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001589 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001590
1591 // use stencil for clipping if clipping is enabled and the clip
1592 // has been written into the stencil.
1593 bool stencilClip = fClipState.fClipInStencil &&
1594 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001595 bool stencilChange = fHWStencilClip != stencilClip ||
1596 fHWDrawState.fStencilSettings != *settings ||
1597 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1598 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001599
1600 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001601
bsalomon@google.comd302f142011-03-03 13:54:13 +00001602 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1603 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001604
bsalomon@google.comd302f142011-03-03 13:54:13 +00001605 if (settings->isDisabled()) {
1606 if (stencilClip) {
1607 settings = &gClipStencilSettings;
1608 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001609 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001610
1611 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001612 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001613 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001614 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001615 #if GR_DEBUG
1616 if (!fStencilWrapOpsSupport) {
1617 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1618 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1619 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1620 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1621 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1622 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1623 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1624 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1625 }
1626 #endif
1627 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1628 GrAssert(stencilBits ||
1629 (GrStencilSettings::gDisabled ==
1630 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001631 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1632 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001633
1634 unsigned int frontRef = settings->fFrontFuncRef;
1635 unsigned int frontMask = settings->fFrontFuncMask;
1636 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001637 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001638
1639 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1640
1641 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1642 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1643 } else {
1644 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1645
1646 ConvertStencilFuncAndMask(settings->fFrontFunc,
1647 stencilClip,
1648 clipStencilMask,
1649 userStencilMask,
1650 &frontRef,
1651 &frontMask);
1652 frontWriteMask &= userStencilMask;
1653 }
1654 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001655 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001656 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001657 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001658 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001659 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001660 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001661 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001662 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001663 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001664
1665 unsigned int backRef = settings->fBackFuncRef;
1666 unsigned int backMask = settings->fBackFuncMask;
1667 unsigned int backWriteMask = settings->fBackWriteMask;
1668
1669
1670 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1671 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1672 backFunc = grToGLStencilFunc[settings->fBackFunc];
1673 } else {
1674 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1675 ConvertStencilFuncAndMask(settings->fBackFunc,
1676 stencilClip,
1677 clipStencilMask,
1678 userStencilMask,
1679 &backRef,
1680 &backMask);
1681 backWriteMask &= userStencilMask;
1682 }
1683
twiz@google.com0f31ca72011-03-18 17:38:11 +00001684 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1685 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1686 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1687 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1688 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001689 grToGLStencilOp[settings->fFrontPassOp],
1690 grToGLStencilOp[settings->fFrontPassOp]));
1691
twiz@google.com0f31ca72011-03-18 17:38:11 +00001692 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001693 grToGLStencilOp[settings->fBackPassOp],
1694 grToGLStencilOp[settings->fBackPassOp]));
1695 } else {
1696 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1697 GR_GL(StencilMask(frontWriteMask));
1698 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1699 grToGLStencilOp[settings->fFrontPassOp],
1700 grToGLStencilOp[settings->fFrontPassOp]));
1701 }
1702 }
1703 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001704 fHWStencilClip = stencilClip;
1705 }
1706}
1707
bsalomon@google.com0650e812011-04-08 18:07:53 +00001708bool GrGpuGL::useSmoothLines() {
1709 // there is a conflict between using smooth lines and our use of
1710 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1711 // but not in a premul-alpha way. So we only use them when our alpha
1712 // is 0xff.
1713
1714 // TODO: write a smarter line frag shader.
1715
1716 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1717 canDisableBlend();
1718}
1719
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001720void GrGpuGL::flushAAState(GrPrimitiveType type) {
1721 if (GR_GL_SUPPORT_DESKTOP) {
1722 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1723 // smooth lines.
1724
1725 // we prefer smooth lines over multisampled lines
1726 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001727 if (GrIsPrimTypeLines(type)) {
1728 bool smooth = useSmoothLines();
1729 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001730 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1731 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001732 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001733 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1734 fHWAAState.fSmoothLineEnabled = false;
1735 }
1736 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1737 fHWAAState.fMSAAEnabled) {
1738 GR_GL(Disable(GR_GL_MULTISAMPLE));
1739 fHWAAState.fMSAAEnabled = false;
1740 }
1741 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1742 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1743 fHWAAState.fMSAAEnabled) {
1744 if (fHWAAState.fMSAAEnabled) {
1745 GR_GL(Disable(GR_GL_MULTISAMPLE));
1746 fHWAAState.fMSAAEnabled = false;
1747 } else {
1748 GR_GL(Enable(GR_GL_MULTISAMPLE));
1749 fHWAAState.fMSAAEnabled = true;
1750 }
1751 }
1752 }
1753}
1754
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001755void GrGpuGL::flushBlend(GrPrimitiveType type,
1756 GrBlendCoeff srcCoeff,
1757 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001758 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1759 if (fHWBlendDisabled) {
1760 GR_GL(Enable(GR_GL_BLEND));
1761 fHWBlendDisabled = false;
1762 }
1763 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1764 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1765 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1766 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1767 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1768 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1769 }
1770 } else {
1771 bool blendOff = canDisableBlend();
1772 if (fHWBlendDisabled != blendOff) {
1773 if (blendOff) {
1774 GR_GL(Disable(GR_GL_BLEND));
1775 } else {
1776 GR_GL(Enable(GR_GL_BLEND));
1777 }
1778 fHWBlendDisabled = blendOff;
1779 }
1780 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001781 if (fHWDrawState.fSrcBlend != srcCoeff ||
1782 fHWDrawState.fDstBlend != dstCoeff) {
1783 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1784 gXfermodeCoeff2Blend[dstCoeff]));
1785 fHWDrawState.fSrcBlend = srcCoeff;
1786 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001787 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001788 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1789 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001790 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1791
1792 float c[] = {
1793 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1794 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1795 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1796 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1797 };
1798 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1799 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1800 }
1801 }
1802 }
1803}
1804
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +00001805static unsigned grToGLFilter(GrSamplerState::Filter filter) {
1806 switch (filter) {
1807 case GrSamplerState::kBilinear_Filter:
1808 case GrSamplerState::k4x4Downsample_Filter:
1809 return GR_GL_LINEAR;
1810 case GrSamplerState::kNearest_Filter:
1811 case GrSamplerState::kConvolution_Filter:
1812 return GR_GL_NEAREST;
1813 default:
1814 GrAssert(!"Unknown filter type");
1815 return GR_GL_LINEAR;
1816 }
1817}
1818
bsalomon@google.comffca4002011-02-22 20:34:01 +00001819bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001820
1821 // GrGpu::setupClipAndFlushState should have already checked this
1822 // and bailed if not true.
1823 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001824
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001825 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001826 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001827 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001828 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001829
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001830 // true for now, but maybe not with GrEffect.
1831 GrAssert(NULL != nextTexture);
1832 // if we created a rt/tex and rendered to it without using a
1833 // texture and now we're texuring from the rt it will still be
1834 // the last bound texture, but it needs resolving. So keep this
1835 // out of the "last != next" check.
1836 GrGLRenderTarget* texRT =
1837 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1838 if (NULL != texRT) {
1839 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001840 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001841
1842 if (fHWDrawState.fTextures[s] != nextTexture) {
1843 setTextureUnit(s);
1844 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1845 #if GR_COLLECT_STATS
1846 ++fStats.fTextureChngCnt;
1847 #endif
1848 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1849 fHWDrawState.fTextures[s] = nextTexture;
bsalomon@google.comcd19a5f2011-06-15 14:00:23 +00001850 // The texture matrix has to compensate for texture width/height
1851 // and NPOT-embedded-in-POT
1852 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001853 }
1854
1855 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1856 const GrGLTexture::TexParams& oldTexParams =
1857 nextTexture->getTexParams();
1858 GrGLTexture::TexParams newTexParams;
1859
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +00001860 newTexParams.fFilter = grToGLFilter(sampler.getFilter());
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001861
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001862 newTexParams.fWrapS =
1863 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1864 newTexParams.fWrapT =
1865 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1866
1867 if (newTexParams.fFilter != oldTexParams.fFilter) {
1868 setTextureUnit(s);
1869 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1870 GR_GL_TEXTURE_MAG_FILTER,
1871 newTexParams.fFilter));
1872 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1873 GR_GL_TEXTURE_MIN_FILTER,
1874 newTexParams.fFilter));
1875 }
1876 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1877 setTextureUnit(s);
1878 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1879 GR_GL_TEXTURE_WRAP_S,
1880 newTexParams.fWrapS));
1881 }
1882 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1883 setTextureUnit(s);
1884 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1885 GR_GL_TEXTURE_WRAP_T,
1886 newTexParams.fWrapT));
1887 }
1888 nextTexture->setTexParams(newTexParams);
reed@google.comac10a2d2010-12-22 21:39:39 +00001889 }
1890 }
1891
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001892 GrIRect* rect = NULL;
1893 GrIRect clipBounds;
1894 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1895 fClip.hasConservativeBounds()) {
1896 fClip.getConservativeBounds().roundOut(&clipBounds);
1897 rect = &clipBounds;
1898 }
1899 this->flushRenderTarget(rect);
1900 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001901
reed@google.comac10a2d2010-12-22 21:39:39 +00001902 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1903 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1904 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001905 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001906 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001907 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001908 }
1909 }
1910
bsalomon@google.comd302f142011-03-03 13:54:13 +00001911 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1912 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001913 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001914 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001915 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001916 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001917 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001918 }
1919 GR_GL(ColorMask(mask, mask, mask, mask));
1920 }
1921
bsalomon@google.comd302f142011-03-03 13:54:13 +00001922 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1923 switch (fCurrDrawState.fDrawFace) {
1924 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001925 GR_GL(Enable(GR_GL_CULL_FACE));
1926 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001927 break;
1928 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001929 GR_GL(Enable(GR_GL_CULL_FACE));
1930 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001931 break;
1932 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001933 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001934 break;
1935 default:
1936 GrCrash("Unknown draw face.");
1937 }
1938 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1939 }
1940
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001941#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001942 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001943 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001944 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001945 NULL == fCurrDrawState.fRenderTarget ||
1946 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001947 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001948 fCurrDrawState.fRenderTarget);
1949 }
1950#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001951
reed@google.comac10a2d2010-12-22 21:39:39 +00001952 flushStencil();
1953
bsalomon@google.comd302f142011-03-03 13:54:13 +00001954 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001955 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001956 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001957}
1958
1959void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001960 if (fHWGeometryState.fVertexBuffer != buffer) {
1961 fHWGeometryState.fArrayPtrsDirty = true;
1962 fHWGeometryState.fVertexBuffer = buffer;
1963 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001964}
1965
1966void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001967 if (fHWGeometryState.fVertexBuffer == buffer) {
1968 // deleting bound buffer does implied bind to 0
1969 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001970 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001971 }
1972}
1973
1974void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001975 fHWGeometryState.fIndexBuffer = buffer;
reed@google.comac10a2d2010-12-22 21:39:39 +00001976}
1977
1978void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001979 if (fHWGeometryState.fIndexBuffer == buffer) {
1980 // deleting bound buffer does implied bind to 0
1981 fHWGeometryState.fIndexBuffer = NULL;
1982 }
1983}
1984
reed@google.comac10a2d2010-12-22 21:39:39 +00001985void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1986 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001987 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001988 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001989 }
1990 if (fHWDrawState.fRenderTarget == renderTarget) {
1991 fHWDrawState.fRenderTarget = NULL;
1992 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001993}
1994
1995void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001996 for (int s = 0; s < kNumStages; ++s) {
1997 if (fCurrDrawState.fTextures[s] == texture) {
1998 fCurrDrawState.fTextures[s] = NULL;
1999 }
2000 if (fHWDrawState.fTextures[s] == texture) {
2001 // deleting bound texture does implied bind to 0
2002 fHWDrawState.fTextures[s] = NULL;
2003 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002004 }
reed@google.comac10a2d2010-12-22 21:39:39 +00002005}
2006
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002007bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00002008 GrGLenum* internalFormat,
2009 GrGLenum* format,
2010 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002011 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002012 case kRGBA_8888_GrPixelConfig:
2013 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00002014 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002015 if (GR_GL_SUPPORT_ES) {
2016 // according to GL_EXT_texture_format_BGRA8888 the *internal*
2017 // format for a BGRA is BGRA not RGBA (as on desktop)
2018 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
2019 } else {
2020 *internalFormat = GR_GL_RGBA;
2021 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00002022 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00002023 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002024 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002025 *format = GR_GL_RGB;
2026 *internalFormat = GR_GL_RGB;
2027 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00002028 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002029 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002030 *format = GR_GL_RGBA;
2031 *internalFormat = GR_GL_RGBA;
2032 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002033 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002034 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002035 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002036 *format = GR_GL_PALETTE8_RGBA8;
2037 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00002038 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00002039 } else {
2040 return false;
2041 }
2042 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002043 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002044 *format = GR_GL_ALPHA;
2045 *internalFormat = GR_GL_ALPHA;
2046 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00002047 break;
2048 default:
2049 return false;
2050 }
2051 return true;
2052}
2053
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002054void GrGpuGL::setTextureUnit(int unit) {
2055 GrAssert(unit >= 0 && unit < kNumStages);
2056 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002057 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002058 fActiveTextureUnitIdx = unit;
2059 }
2060}
bsalomon@google.com316f99232011-01-13 21:28:12 +00002061
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002062void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002063 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2064 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002065 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
2066 }
2067}
2068
reed@google.comac10a2d2010-12-22 21:39:39 +00002069/* On ES the internalFormat and format must match for TexImage and we use
2070 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
2071 decide the internalFormat. However, on ES internalFormat for
2072 RenderBufferStorage* has to be a specific format (not a base format like
2073 GL_RGBA).
2074 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002075bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002076 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002077 case kRGBA_8888_GrPixelConfig:
2078 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002079 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002080 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00002081 return true;
2082 } else {
2083 return false;
2084 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002085 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002086 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2087 // with FBO extension desktop GL has
2088 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002089 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002090 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002091 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002092 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002093 return true;
2094 default:
2095 return false;
2096 }
2097}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002098
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002099void GrGpuGL::resetDirtyFlags() {
2100 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2101}
2102
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002103void GrGpuGL::setBuffers(bool indexed,
2104 int* extraVertexOffset,
2105 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002106
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002107 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002108
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002109 const GeometryPoolState& geoPoolState = this->getGeomPoolState();
2110
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002111 GrGLVertexBuffer* vbuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002112 switch (this->getGeomSrc().fVertexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002113 case kBuffer_GeometrySrcType:
2114 *extraVertexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002115 vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002116 break;
2117 case kArray_GeometrySrcType:
2118 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002119 this->finalizeReservedVertices();
2120 *extraVertexOffset = geoPoolState.fPoolStartVertex;
2121 vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002122 break;
2123 default:
2124 vbuf = NULL; // suppress warning
2125 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002126 }
2127
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002128 GrAssert(NULL != vbuf);
2129 GrAssert(!vbuf->isLocked());
2130 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002131 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002132 fHWGeometryState.fArrayPtrsDirty = true;
2133 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002134 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002135
2136 if (indexed) {
2137 GrAssert(NULL != extraIndexOffset);
2138
2139 GrGLIndexBuffer* ibuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002140 switch (this->getGeomSrc().fIndexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002141 case kBuffer_GeometrySrcType:
2142 *extraIndexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002143 ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002144 break;
2145 case kArray_GeometrySrcType:
2146 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002147 this->finalizeReservedIndices();
2148 *extraIndexOffset = geoPoolState.fPoolStartIndex;
2149 ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002150 break;
2151 default:
2152 ibuf = NULL; // suppress warning
2153 GrCrash("Unknown geometry src type!");
2154 }
2155
2156 GrAssert(NULL != ibuf);
2157 GrAssert(!ibuf->isLocked());
2158 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002159 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002160 fHWGeometryState.fIndexBuffer = ibuf;
2161 }
2162 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002163}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002164
2165int GrGpuGL::getMaxEdges() const {
2166 // FIXME: This is a pessimistic estimate based on how many other things
2167 // want to add uniforms. This should be centralized somewhere.
2168 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2169}
bsalomon@google.comfe676522011-06-17 18:12:21 +00002170