blob: 1a9d7fe3255de18715282d02536aa5c87801fbf4 [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
793 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000794 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000795 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000796 GrPrintf("AA RT requested but not supported on this platform.");
797 }
798
799 GR_GL(GenTextures(1, &glDesc.fTextureID));
800 if (!glDesc.fTextureID) {
801 return return_null_texture();
802 }
803
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000804 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000805
reed@google.com5e762232011-04-04 18:15:49 +0000806 // in case we need a temporary, trimmed copy of the src pixels
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000807 SkAutoSMalloc<128 * 128> trimStorage;
reed@google.com5e762232011-04-04 18:15:49 +0000808
reed@google.comac10a2d2010-12-22 21:39:39 +0000809 /*
810 * check if our srcData has extra bytes past each row. If so, we need
811 * to trim those off here, since GL doesn't let us pass the rowBytes as
812 * a parameter to glTexImage2D
813 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000814 if (GR_GL_SUPPORT_DESKTOP) {
815 if (srcData) {
816 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
817 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000818 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000819 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000820 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
821 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000822 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000823 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000824 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000825 char* dst = (char*)trimStorage.realloc(trimSize);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000826 for (int y = 0; y < desc.fHeight; y++) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000827 memcpy(dst, src, trimRowBytes);
828 src += rowBytes;
829 dst += trimRowBytes;
830 }
831 // now point srcData to our trimmed version
832 srcData = trimStorage.get();
833 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000834 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000835
reed@google.comac10a2d2010-12-22 21:39:39 +0000836 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000837 if (!this->npotRenderTargetSupport()) {
838 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
839 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
840 }
841
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000842 glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
843 glDesc.fAllocWidth);
844 glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
845 glDesc.fAllocHeight);
846 if (glDesc.fAllocWidth > fMaxRenderTargetSize ||
847 glDesc.fAllocHeight > fMaxRenderTargetSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000848 return return_null_texture();
849 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000850 } else if (!this->npotTextureSupport()) {
851 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
852 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000853 if (glDesc.fAllocWidth > fMaxTextureSize ||
854 glDesc.fAllocHeight > fMaxTextureSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000855 return return_null_texture();
856 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000857 }
858
twiz@google.com0f31ca72011-03-18 17:38:11 +0000859 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
860 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
861 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000862 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000863 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
864 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000865 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000866 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
867 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000868 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000869 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
870 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000871 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000872
twiz@google.com0f31ca72011-03-18 17:38:11 +0000873 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000874 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000875 supports8BitPalette()) {
876 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
877 GrAssert(desc.fWidth == glDesc.fAllocWidth);
878 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000879 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000880 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000881 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000882 glDesc.fAllocWidth, glDesc.fAllocHeight,
883 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000884 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000885 } else {
886 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
887 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000888 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000889 glDesc.fAllocWidth, glDesc.fAllocHeight,
890 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000891 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000892 desc.fHeight, glDesc.fUploadFormat,
893 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000894 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000895
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000896 int extraW = glDesc.fAllocWidth - desc.fWidth;
897 int extraH = glDesc.fAllocHeight - desc.fHeight;
898 int maxTexels = extraW * extraH;
reed@google.comac10a2d2010-12-22 21:39:39 +0000899 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
900 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
901
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000902 SkAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
reed@google.comac10a2d2010-12-22 21:39:39 +0000903
904 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
905 if (extraH) {
906 uint8_t* lastRowStart = (uint8_t*) srcData +
907 (desc.fHeight - 1) * rowSize;
908 uint8_t* extraRowStart = (uint8_t*)texels.get();
909
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000910 for (int i = 0; i < extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000911 memcpy(extraRowStart, lastRowStart, rowSize);
912 extraRowStart += rowSize;
913 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000914 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000915 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
916 texels.get()));
917 }
918 if (extraW) {
919 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
920 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000921 for (int j = 0; j < desc.fHeight; ++j) {
922 for (int i = 0; i < extraW; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000923 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
924 extraTexel += glDesc.fUploadByteCount;
925 }
926 edgeTexel += rowSize;
927 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000928 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000929 desc.fHeight, glDesc.fUploadFormat,
930 glDesc.fUploadType, texels.get()));
931 }
932 if (extraW && extraH) {
933 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
934 - glDesc.fUploadByteCount;
935 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000936 for (int i = 0; i < extraW*extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000937 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
938 extraTexel += glDesc.fUploadByteCount;
939 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000940 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000941 extraW, extraH, glDesc.fUploadFormat,
942 glDesc.fUploadType, texels.get()));
943 }
944
945 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000946 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000947 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
948 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000949 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000950 }
951 }
952
953 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
954
955 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
956 rtIDs.fStencilRenderbufferID = 0;
957 rtIDs.fMSColorRenderbufferID = 0;
958 rtIDs.fRTFBOID = 0;
959 rtIDs.fTexFBOID = 0;
960 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000961 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000962
963 if (renderTarget) {
964#if GR_COLLECT_STATS
965 ++fStats.fRenderTargetCreateCnt;
966#endif
967 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000968 GrGLenum status;
969 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000970
971 // If need have both RT flag and srcData we have
972 // to invert the data before uploading because FBO
973 // will be rendered bottom up
974 GrAssert(NULL == srcData);
975 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
976
twiz@google.com59a190b2011-03-14 21:23:01 +0000977 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000978 GrAssert(rtIDs.fTexFBOID);
979
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000980 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000981 // to one and then resolve to the texture bound to the other.
982 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000983 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000984 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000985 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000986 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
987 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000988 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000989 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000990 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
991 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000992 return return_null_texture();
993 }
994 } else {
995 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
996 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000997 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000998 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000999 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +00001000 }
1001
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001002 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +00001003 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001004 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +00001005 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001006
twiz@google.com0f31ca72011-03-18 17:38:11 +00001007 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001008
bsalomon@google.comfe676522011-06-17 18:12:21 +00001009 int stencilFmtCnt;
bsalomon@google.comfe676522011-06-17 18:12:21 +00001010 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001011 stencilFmtCnt = fStencilFormats.count();
bsalomon@google.comfe676522011-06-17 18:12:21 +00001012 } else {
1013 stencilFmtCnt = 1; // only 1 attempt when we don't need a stencil
1014 }
1015
1016 for (int i = 0; i < stencilFmtCnt; ++i) {
1017 // we start with the last stencil format that succeeded in hopes
1018 // that we won't go through this loop more than once after the
1019 // first (painful) stencil creation.
1020 int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
1021
reed@google.comac10a2d2010-12-22 21:39:39 +00001022 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001023 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001024 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001025 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001026 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001027 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001028 samples,
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001029 fStencilFormats[sIdx].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +00001030 glDesc.fAllocWidth,
1031 glDesc.fAllocHeight));
1032 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001033 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001034 fStencilFormats[sIdx].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +00001035 glDesc.fAllocWidth,
1036 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +00001037 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001038 err = GrGLGetGLInterface()->fGetError();
1039 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001040 continue;
1041 }
1042 }
1043 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
1044 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001045 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001046 rtIDs.fMSColorRenderbufferID));
1047 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001048 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001049 samples,
1050 msColorRenderbufferFormat,
1051 glDesc.fAllocWidth,
1052 glDesc.fAllocHeight));
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 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001058 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001059
1060#if GR_COLLECT_STATS
1061 ++fStats.fRenderTargetChngCnt;
1062#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001063 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1064 GR_GL_COLOR_ATTACHMENT0,
1065 GR_GL_TEXTURE_2D,
1066 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001067 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001068 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1069 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001070 continue;
1071 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001072 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001073 #if GR_COLLECT_STATS
1074 ++fStats.fRenderTargetChngCnt;
1075 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001076 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1077 GR_GL_COLOR_ATTACHMENT0,
1078 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001079 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001080
1081 }
1082 if (rtIDs.fStencilRenderbufferID) {
1083 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001084 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1085 GR_GL_STENCIL_ATTACHMENT,
1086 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001087 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001088 // if it is a packed format bind to depth also, otherwise
1089 // we may get an unsupported fbo completeness result
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001090 if (fStencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001091 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1092 GR_GL_DEPTH_ATTACHMENT,
1093 GR_GL_RENDERBUFFER,
1094 rtIDs.fStencilRenderbufferID));
1095 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001096 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001097 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001098
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001099 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001100 // undo the depth bind
1101 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001102 fStencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001103 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1104 GR_GL_DEPTH_ATTACHMENT,
1105 GR_GL_RENDERBUFFER,
1106 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001107 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001108 continue;
1109 }
1110 // we're successful!
1111 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001112 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comfe676522011-06-17 18:12:21 +00001113 fLastSuccessfulStencilFmtIdx = sIdx;
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001114 if (gUNKNOWN_BITCOUNT == fStencilFormats[sIdx].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001115 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001116 } else {
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +00001117 glDesc.fStencilBits = fStencilFormats[sIdx].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001118 }
1119 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001120 break;
1121 }
1122 if (failed) {
1123 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001124 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001125 }
1126 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001127 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001128 }
1129 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001130 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001131 }
1132 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001133 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001134 }
1135 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1136 return return_null_texture();
1137 }
1138 }
1139#ifdef TRACE_TEXTURE_CREATION
1140 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1141 tex->fTextureID, width, height, tex->fUploadByteCount);
1142#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001143 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001144
1145 if (0 != rtIDs.fTexFBOID) {
1146 GrRenderTarget* rt = tex->asRenderTarget();
1147 // We've messed with FBO state but may not have set the correct viewport
1148 // so just dirty the rendertarget state to force a resend.
1149 fHWDrawState.fRenderTarget = NULL;
1150
1151 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001152 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001153 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1154 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001155 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 fCurrDrawState.fRenderTarget = rtSave;
1157 }
1158 }
1159 return tex;
1160}
1161
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001162GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001163 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001164 GR_GL(GenBuffers(1, &id));
1165 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001166 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001167 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001168 GrGLClearErr();
1169 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001170 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1171 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1172 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001173 GR_GL(DeleteBuffers(1, &id));
1174 // deleting bound buffer does implicit bind to 0
1175 fHWGeometryState.fVertexBuffer = NULL;
1176 return NULL;
1177 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001178 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001179 size, dynamic);
1180 fHWGeometryState.fVertexBuffer = vertexBuffer;
1181 return vertexBuffer;
1182 }
1183 return NULL;
1184}
1185
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001186GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001187 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001188 GR_GL(GenBuffers(1, &id));
1189 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001190 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001191 GrGLClearErr();
1192 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001193 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1194 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1195 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001196 GR_GL(DeleteBuffers(1, &id));
1197 // deleting bound buffer does implicit bind to 0
1198 fHWGeometryState.fIndexBuffer = NULL;
1199 return NULL;
1200 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001201 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001202 size, dynamic);
1203 fHWGeometryState.fIndexBuffer = indexBuffer;
1204 return indexBuffer;
1205 }
1206 return NULL;
1207}
1208
reed@google.comac10a2d2010-12-22 21:39:39 +00001209void GrGpuGL::flushScissor(const GrIRect* rect) {
1210 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001211 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001212 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001213
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001214 GrGLIRect scissor;
1215 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001216 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001217 rect->width(), rect->height());
1218 if (scissor.contains(vp)) {
1219 rect = NULL;
1220 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001221 }
1222
1223 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001224 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001225 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001226 fHWBounds.fScissorRect = scissor;
1227 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001228 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001229 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001230 fHWBounds.fScissorEnabled = true;
1231 }
1232 } else {
1233 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001234 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001235 fHWBounds.fScissorEnabled = false;
1236 }
1237 }
1238}
1239
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001240void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001241 if (NULL == fCurrDrawState.fRenderTarget) {
1242 return;
1243 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001244 GrIRect r;
1245 if (NULL != rect) {
1246 // flushScissor expects rect to be clipped to the target.
1247 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001248 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1249 fCurrDrawState.fRenderTarget->height());
1250 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001251 rect = &r;
1252 } else {
1253 return;
1254 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001255 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001256 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001257 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001258 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001259 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001260 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1261 GrColorUnpackG(color)/255.f,
1262 GrColorUnpackB(color)/255.f,
1263 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001264 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001265}
1266
bsalomon@google.com398109c2011-04-14 18:40:27 +00001267void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001268 if (NULL == fCurrDrawState.fRenderTarget) {
1269 return;
1270 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001271
1272 this->flushRenderTarget(&GrIRect::EmptyIRect());
1273
reed@google.comac10a2d2010-12-22 21:39:39 +00001274 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001275 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001276 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001277 }
1278 GR_GL(StencilMask(mask));
1279 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001280 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001281 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001282}
1283
bsalomon@google.com398109c2011-04-14 18:40:27 +00001284void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001285 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001286#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001287 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001288 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001289 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001290#else
1291 // we could just clear the clip bit but when we go through
1292 // angle a partial stencil mask will cause clears to be
1293 // turned into draws. Our contract on GrDrawTarget says that
1294 // changing the clip between stencil passes may or may not
1295 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001296 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001297#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001298 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001299 flushScissor(&rect);
1300 GR_GL(StencilMask(clipStencilMask));
1301 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001302 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001303 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001304}
1305
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001306void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001307 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001308}
1309
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001310bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1311 int left, int top, int width, int height,
1312 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001313 GrGLenum internalFormat; // we don't use this for glReadPixels
1314 GrGLenum format;
1315 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001316 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1317 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001318 }
1319 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1320 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1321 switch (tgt->getResolveType()) {
1322 case GrGLRenderTarget::kCantResolve_ResolveType:
1323 return false;
1324 case GrGLRenderTarget::kAutoResolves_ResolveType:
1325 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1326 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001327 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001328 break;
1329 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001330 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001331 // we don't track the state of the READ FBO ID.
1332 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1333 break;
1334 default:
1335 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001336 }
1337
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001338 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001339
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001340 // the read rect is viewport-relative
1341 GrGLIRect readRect;
1342 readRect.setRelativeTo(glvp, left, top, width, height);
1343 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001344 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001345 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001346
1347 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1348 // API presents top-to-bottom
1349 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001350 size_t stride = width * GrBytesPerPixel(config);
bsalomon@google.com3582bf92011-06-30 21:32:31 +00001351 SkAutoMalloc rowStorage(stride);
reed@google.comac10a2d2010-12-22 21:39:39 +00001352 void* tmp = rowStorage.get();
1353
1354 const int halfY = height >> 1;
1355 char* top = reinterpret_cast<char*>(buffer);
1356 char* bottom = top + (height - 1) * stride;
1357 for (int y = 0; y < halfY; y++) {
1358 memcpy(tmp, top, stride);
1359 memcpy(top, bottom, stride);
1360 memcpy(bottom, tmp, stride);
1361 top += stride;
1362 bottom -= stride;
1363 }
1364 }
1365 return true;
1366}
1367
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001368void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001369
1370 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1371
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001372 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001373 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001374 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001375 #if GR_COLLECT_STATS
1376 ++fStats.fRenderTargetChngCnt;
1377 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001378 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001379 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1380 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001381 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001382 }
1383 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001384 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001385 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001386 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001387 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001388 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001389 fHWBounds.fViewportRect = vp;
1390 }
1391 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001392 if (NULL == bound || !bound->isEmpty()) {
1393 rt->flagAsNeedingResolve(bound);
1394 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001395}
1396
twiz@google.com0f31ca72011-03-18 17:38:11 +00001397GrGLenum gPrimitiveType2GLMode[] = {
1398 GR_GL_TRIANGLES,
1399 GR_GL_TRIANGLE_STRIP,
1400 GR_GL_TRIANGLE_FAN,
1401 GR_GL_POINTS,
1402 GR_GL_LINES,
1403 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001404};
1405
bsalomon@google.comd302f142011-03-03 13:54:13 +00001406#define SWAP_PER_DRAW 0
1407
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001408#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001409 #if GR_MAC_BUILD
1410 #include <AGL/agl.h>
1411 #elif GR_WIN32_BUILD
1412 void SwapBuf() {
1413 DWORD procID = GetCurrentProcessId();
1414 HWND hwnd = GetTopWindow(GetDesktopWindow());
1415 while(hwnd) {
1416 DWORD wndProcID = 0;
1417 GetWindowThreadProcessId(hwnd, &wndProcID);
1418 if(wndProcID == procID) {
1419 SwapBuffers(GetDC(hwnd));
1420 }
1421 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1422 }
1423 }
1424 #endif
1425#endif
1426
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001427void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type,
1428 uint32_t startVertex,
1429 uint32_t startIndex,
1430 uint32_t vertexCount,
1431 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001432 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1433
twiz@google.com0f31ca72011-03-18 17:38:11 +00001434 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001435
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001436 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1437 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1438
1439 // our setupGeometry better have adjusted this to zero since
1440 // DrawElements always draws from the begining of the arrays for idx 0.
1441 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001442
1443 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001444 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001445#if SWAP_PER_DRAW
1446 glFlush();
1447 #if GR_MAC_BUILD
1448 aglSwapBuffers(aglGetCurrentContext());
1449 int set_a_break_pt_here = 9;
1450 aglSwapBuffers(aglGetCurrentContext());
1451 #elif GR_WIN32_BUILD
1452 SwapBuf();
1453 int set_a_break_pt_here = 9;
1454 SwapBuf();
1455 #endif
1456#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001457}
1458
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001459void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
1460 uint32_t startVertex,
1461 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001462 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1463
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001464 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1465
1466 // our setupGeometry better have adjusted this to zero.
1467 // DrawElements doesn't take an offset so we always adjus the startVertex.
1468 GrAssert(0 == startVertex);
1469
1470 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1471 // account for startVertex in the DrawElements case. So we always
1472 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001473 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001474#if SWAP_PER_DRAW
1475 glFlush();
1476 #if GR_MAC_BUILD
1477 aglSwapBuffers(aglGetCurrentContext());
1478 int set_a_break_pt_here = 9;
1479 aglSwapBuffers(aglGetCurrentContext());
1480 #elif GR_WIN32_BUILD
1481 SwapBuf();
1482 int set_a_break_pt_here = 9;
1483 SwapBuf();
1484 #endif
1485#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001486}
1487
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001488void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001489
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001490 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001491 GrAssert(kNone_MSFBO != fMSFBOType);
1492 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001493 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001494 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001495 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001496 rt->textureFBOID()));
1497 #if GR_COLLECT_STATS
1498 ++fStats.fRenderTargetChngCnt;
1499 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001500 // make sure we go through flushRenderTarget() since we've modified
1501 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001502 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001503 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001504 const GrIRect dirtyRect = rt->getResolveRect();
1505 GrGLIRect r;
1506 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1507 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001508
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001509 if (kAppleES_MSFBO == fMSFBOType) {
1510 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001511 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001512 GR_GL(Scissor(r.fLeft, r.fBottom,
1513 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001514 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001515 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001516 fHWBounds.fScissorEnabled = true;
1517 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001518 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001519 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001520 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1521 flushScissor(NULL);
1522 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001523 int right = r.fLeft + r.fWidth;
1524 int top = r.fBottom + r.fHeight;
1525 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1526 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001527 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001528 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001529 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001530 }
1531}
1532
twiz@google.com0f31ca72011-03-18 17:38:11 +00001533static const GrGLenum grToGLStencilFunc[] = {
1534 GR_GL_ALWAYS, // kAlways_StencilFunc
1535 GR_GL_NEVER, // kNever_StencilFunc
1536 GR_GL_GREATER, // kGreater_StencilFunc
1537 GR_GL_GEQUAL, // kGEqual_StencilFunc
1538 GR_GL_LESS, // kLess_StencilFunc
1539 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1540 GR_GL_EQUAL, // kEqual_StencilFunc,
1541 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001542};
1543GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1544GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1545GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1546GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1547GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1548GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1549GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1550GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1551GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1552
twiz@google.com0f31ca72011-03-18 17:38:11 +00001553static const GrGLenum grToGLStencilOp[] = {
1554 GR_GL_KEEP, // kKeep_StencilOp
1555 GR_GL_REPLACE, // kReplace_StencilOp
1556 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1557 GR_GL_INCR, // kIncClamp_StencilOp
1558 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1559 GR_GL_DECR, // kDecClamp_StencilOp
1560 GR_GL_ZERO, // kZero_StencilOp
1561 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001562};
1563GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1564GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1565GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1566GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1567GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1568GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1569GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1570GR_STATIC_ASSERT(6 == kZero_StencilOp);
1571GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1572
reed@google.comac10a2d2010-12-22 21:39:39 +00001573void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001574 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001575
1576 // use stencil for clipping if clipping is enabled and the clip
1577 // has been written into the stencil.
1578 bool stencilClip = fClipState.fClipInStencil &&
1579 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001580 bool stencilChange = fHWStencilClip != stencilClip ||
1581 fHWDrawState.fStencilSettings != *settings ||
1582 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1583 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001584
1585 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001586
bsalomon@google.comd302f142011-03-03 13:54:13 +00001587 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1588 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001589
bsalomon@google.comd302f142011-03-03 13:54:13 +00001590 if (settings->isDisabled()) {
1591 if (stencilClip) {
1592 settings = &gClipStencilSettings;
1593 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001594 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001595
1596 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001597 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001598 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001599 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001600 #if GR_DEBUG
1601 if (!fStencilWrapOpsSupport) {
1602 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1603 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1604 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1605 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1606 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1607 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1608 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1609 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1610 }
1611 #endif
1612 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1613 GrAssert(stencilBits ||
1614 (GrStencilSettings::gDisabled ==
1615 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001616 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1617 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001618
1619 unsigned int frontRef = settings->fFrontFuncRef;
1620 unsigned int frontMask = settings->fFrontFuncMask;
1621 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001622 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001623
1624 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1625
1626 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1627 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1628 } else {
1629 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1630
1631 ConvertStencilFuncAndMask(settings->fFrontFunc,
1632 stencilClip,
1633 clipStencilMask,
1634 userStencilMask,
1635 &frontRef,
1636 &frontMask);
1637 frontWriteMask &= userStencilMask;
1638 }
1639 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001640 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001641 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001642 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001643 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001644 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001645 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001646 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001647 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001648 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001649
1650 unsigned int backRef = settings->fBackFuncRef;
1651 unsigned int backMask = settings->fBackFuncMask;
1652 unsigned int backWriteMask = settings->fBackWriteMask;
1653
1654
1655 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1656 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1657 backFunc = grToGLStencilFunc[settings->fBackFunc];
1658 } else {
1659 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1660 ConvertStencilFuncAndMask(settings->fBackFunc,
1661 stencilClip,
1662 clipStencilMask,
1663 userStencilMask,
1664 &backRef,
1665 &backMask);
1666 backWriteMask &= userStencilMask;
1667 }
1668
twiz@google.com0f31ca72011-03-18 17:38:11 +00001669 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1670 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1671 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1672 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1673 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001674 grToGLStencilOp[settings->fFrontPassOp],
1675 grToGLStencilOp[settings->fFrontPassOp]));
1676
twiz@google.com0f31ca72011-03-18 17:38:11 +00001677 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001678 grToGLStencilOp[settings->fBackPassOp],
1679 grToGLStencilOp[settings->fBackPassOp]));
1680 } else {
1681 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1682 GR_GL(StencilMask(frontWriteMask));
1683 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1684 grToGLStencilOp[settings->fFrontPassOp],
1685 grToGLStencilOp[settings->fFrontPassOp]));
1686 }
1687 }
1688 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001689 fHWStencilClip = stencilClip;
1690 }
1691}
1692
bsalomon@google.com0650e812011-04-08 18:07:53 +00001693bool GrGpuGL::useSmoothLines() {
1694 // there is a conflict between using smooth lines and our use of
1695 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1696 // but not in a premul-alpha way. So we only use them when our alpha
1697 // is 0xff.
1698
1699 // TODO: write a smarter line frag shader.
1700
1701 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1702 canDisableBlend();
1703}
1704
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001705void GrGpuGL::flushAAState(GrPrimitiveType type) {
1706 if (GR_GL_SUPPORT_DESKTOP) {
1707 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1708 // smooth lines.
1709
1710 // we prefer smooth lines over multisampled lines
1711 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001712 if (GrIsPrimTypeLines(type)) {
1713 bool smooth = useSmoothLines();
1714 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001715 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1716 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001717 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001718 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1719 fHWAAState.fSmoothLineEnabled = false;
1720 }
1721 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1722 fHWAAState.fMSAAEnabled) {
1723 GR_GL(Disable(GR_GL_MULTISAMPLE));
1724 fHWAAState.fMSAAEnabled = false;
1725 }
1726 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1727 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1728 fHWAAState.fMSAAEnabled) {
1729 if (fHWAAState.fMSAAEnabled) {
1730 GR_GL(Disable(GR_GL_MULTISAMPLE));
1731 fHWAAState.fMSAAEnabled = false;
1732 } else {
1733 GR_GL(Enable(GR_GL_MULTISAMPLE));
1734 fHWAAState.fMSAAEnabled = true;
1735 }
1736 }
1737 }
1738}
1739
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001740void GrGpuGL::flushBlend(GrPrimitiveType type,
1741 GrBlendCoeff srcCoeff,
1742 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001743 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1744 if (fHWBlendDisabled) {
1745 GR_GL(Enable(GR_GL_BLEND));
1746 fHWBlendDisabled = false;
1747 }
1748 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1749 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1750 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1751 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1752 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1753 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1754 }
1755 } else {
1756 bool blendOff = canDisableBlend();
1757 if (fHWBlendDisabled != blendOff) {
1758 if (blendOff) {
1759 GR_GL(Disable(GR_GL_BLEND));
1760 } else {
1761 GR_GL(Enable(GR_GL_BLEND));
1762 }
1763 fHWBlendDisabled = blendOff;
1764 }
1765 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001766 if (fHWDrawState.fSrcBlend != srcCoeff ||
1767 fHWDrawState.fDstBlend != dstCoeff) {
1768 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1769 gXfermodeCoeff2Blend[dstCoeff]));
1770 fHWDrawState.fSrcBlend = srcCoeff;
1771 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001772 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001773 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1774 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001775 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1776
1777 float c[] = {
1778 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1779 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1780 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1781 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1782 };
1783 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1784 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1785 }
1786 }
1787 }
1788}
1789
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +00001790static unsigned grToGLFilter(GrSamplerState::Filter filter) {
1791 switch (filter) {
1792 case GrSamplerState::kBilinear_Filter:
1793 case GrSamplerState::k4x4Downsample_Filter:
1794 return GR_GL_LINEAR;
1795 case GrSamplerState::kNearest_Filter:
1796 case GrSamplerState::kConvolution_Filter:
1797 return GR_GL_NEAREST;
1798 default:
1799 GrAssert(!"Unknown filter type");
1800 return GR_GL_LINEAR;
1801 }
1802}
1803
bsalomon@google.comffca4002011-02-22 20:34:01 +00001804bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001805
1806 // GrGpu::setupClipAndFlushState should have already checked this
1807 // and bailed if not true.
1808 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001809
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001810 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001811 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001812 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001813 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001814
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001815 // true for now, but maybe not with GrEffect.
1816 GrAssert(NULL != nextTexture);
1817 // if we created a rt/tex and rendered to it without using a
1818 // texture and now we're texuring from the rt it will still be
1819 // the last bound texture, but it needs resolving. So keep this
1820 // out of the "last != next" check.
1821 GrGLRenderTarget* texRT =
1822 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1823 if (NULL != texRT) {
1824 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001825 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001826
1827 if (fHWDrawState.fTextures[s] != nextTexture) {
1828 setTextureUnit(s);
1829 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1830 #if GR_COLLECT_STATS
1831 ++fStats.fTextureChngCnt;
1832 #endif
1833 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1834 fHWDrawState.fTextures[s] = nextTexture;
bsalomon@google.comcd19a5f2011-06-15 14:00:23 +00001835 // The texture matrix has to compensate for texture width/height
1836 // and NPOT-embedded-in-POT
1837 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001838 }
1839
1840 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1841 const GrGLTexture::TexParams& oldTexParams =
1842 nextTexture->getTexParams();
1843 GrGLTexture::TexParams newTexParams;
1844
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +00001845 newTexParams.fFilter = grToGLFilter(sampler.getFilter());
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001846
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001847 newTexParams.fWrapS =
1848 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1849 newTexParams.fWrapT =
1850 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1851
1852 if (newTexParams.fFilter != oldTexParams.fFilter) {
1853 setTextureUnit(s);
1854 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1855 GR_GL_TEXTURE_MAG_FILTER,
1856 newTexParams.fFilter));
1857 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1858 GR_GL_TEXTURE_MIN_FILTER,
1859 newTexParams.fFilter));
1860 }
1861 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1862 setTextureUnit(s);
1863 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1864 GR_GL_TEXTURE_WRAP_S,
1865 newTexParams.fWrapS));
1866 }
1867 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1868 setTextureUnit(s);
1869 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1870 GR_GL_TEXTURE_WRAP_T,
1871 newTexParams.fWrapT));
1872 }
1873 nextTexture->setTexParams(newTexParams);
reed@google.comac10a2d2010-12-22 21:39:39 +00001874 }
1875 }
1876
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001877 GrIRect* rect = NULL;
1878 GrIRect clipBounds;
1879 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1880 fClip.hasConservativeBounds()) {
1881 fClip.getConservativeBounds().roundOut(&clipBounds);
1882 rect = &clipBounds;
1883 }
1884 this->flushRenderTarget(rect);
1885 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001886
reed@google.comac10a2d2010-12-22 21:39:39 +00001887 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1888 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1889 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001890 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001891 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001892 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001893 }
1894 }
1895
bsalomon@google.comd302f142011-03-03 13:54:13 +00001896 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1897 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001898 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001899 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001900 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001901 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001902 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001903 }
1904 GR_GL(ColorMask(mask, mask, mask, mask));
1905 }
1906
bsalomon@google.comd302f142011-03-03 13:54:13 +00001907 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1908 switch (fCurrDrawState.fDrawFace) {
1909 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001910 GR_GL(Enable(GR_GL_CULL_FACE));
1911 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001912 break;
1913 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001914 GR_GL(Enable(GR_GL_CULL_FACE));
1915 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001916 break;
1917 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001918 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001919 break;
1920 default:
1921 GrCrash("Unknown draw face.");
1922 }
1923 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1924 }
1925
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001926#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001927 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001928 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001929 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001930 NULL == fCurrDrawState.fRenderTarget ||
1931 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001932 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001933 fCurrDrawState.fRenderTarget);
1934 }
1935#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001936
reed@google.comac10a2d2010-12-22 21:39:39 +00001937 flushStencil();
1938
bsalomon@google.comd302f142011-03-03 13:54:13 +00001939 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001940 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001941 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001942}
1943
1944void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001945 if (fHWGeometryState.fVertexBuffer != buffer) {
1946 fHWGeometryState.fArrayPtrsDirty = true;
1947 fHWGeometryState.fVertexBuffer = buffer;
1948 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001949}
1950
1951void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001952 if (fHWGeometryState.fVertexBuffer == buffer) {
1953 // deleting bound buffer does implied bind to 0
1954 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001955 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001956 }
1957}
1958
1959void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001960 fHWGeometryState.fIndexBuffer = buffer;
reed@google.comac10a2d2010-12-22 21:39:39 +00001961}
1962
1963void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001964 if (fHWGeometryState.fIndexBuffer == buffer) {
1965 // deleting bound buffer does implied bind to 0
1966 fHWGeometryState.fIndexBuffer = NULL;
1967 }
1968}
1969
reed@google.comac10a2d2010-12-22 21:39:39 +00001970void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1971 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001972 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001973 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001974 }
1975 if (fHWDrawState.fRenderTarget == renderTarget) {
1976 fHWDrawState.fRenderTarget = NULL;
1977 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001978}
1979
1980void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001981 for (int s = 0; s < kNumStages; ++s) {
1982 if (fCurrDrawState.fTextures[s] == texture) {
1983 fCurrDrawState.fTextures[s] = NULL;
1984 }
1985 if (fHWDrawState.fTextures[s] == texture) {
1986 // deleting bound texture does implied bind to 0
1987 fHWDrawState.fTextures[s] = NULL;
1988 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001989 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001990}
1991
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001992bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001993 GrGLenum* internalFormat,
1994 GrGLenum* format,
1995 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001996 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001997 case kRGBA_8888_GrPixelConfig:
1998 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001999 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002000 if (GR_GL_SUPPORT_ES) {
2001 // according to GL_EXT_texture_format_BGRA8888 the *internal*
2002 // format for a BGRA is BGRA not RGBA (as on desktop)
2003 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
2004 } else {
2005 *internalFormat = GR_GL_RGBA;
2006 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00002007 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00002008 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002009 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002010 *format = GR_GL_RGB;
2011 *internalFormat = GR_GL_RGB;
2012 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00002013 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002014 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002015 *format = GR_GL_RGBA;
2016 *internalFormat = GR_GL_RGBA;
2017 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002018 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002019 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002020 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002021 *format = GR_GL_PALETTE8_RGBA8;
2022 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00002023 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00002024 } else {
2025 return false;
2026 }
2027 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002028 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002029 *format = GR_GL_ALPHA;
2030 *internalFormat = GR_GL_ALPHA;
2031 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00002032 break;
2033 default:
2034 return false;
2035 }
2036 return true;
2037}
2038
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002039void GrGpuGL::setTextureUnit(int unit) {
2040 GrAssert(unit >= 0 && unit < kNumStages);
2041 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002042 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002043 fActiveTextureUnitIdx = unit;
2044 }
2045}
bsalomon@google.com316f99232011-01-13 21:28:12 +00002046
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002047void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002048 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2049 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002050 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
2051 }
2052}
2053
reed@google.comac10a2d2010-12-22 21:39:39 +00002054/* On ES the internalFormat and format must match for TexImage and we use
2055 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
2056 decide the internalFormat. However, on ES internalFormat for
2057 RenderBufferStorage* has to be a specific format (not a base format like
2058 GL_RGBA).
2059 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002060bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002061 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002062 case kRGBA_8888_GrPixelConfig:
2063 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002064 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002065 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00002066 return true;
2067 } else {
2068 return false;
2069 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002070 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002071 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2072 // with FBO extension desktop GL has
2073 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002074 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002075 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002076 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002077 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002078 return true;
2079 default:
2080 return false;
2081 }
2082}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002083
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002084void GrGpuGL::resetDirtyFlags() {
2085 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2086}
2087
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002088void GrGpuGL::setBuffers(bool indexed,
2089 int* extraVertexOffset,
2090 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002091
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002092 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002093
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002094 const GeometryPoolState& geoPoolState = this->getGeomPoolState();
2095
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002096 GrGLVertexBuffer* vbuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002097 switch (this->getGeomSrc().fVertexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002098 case kBuffer_GeometrySrcType:
2099 *extraVertexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002100 vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002101 break;
2102 case kArray_GeometrySrcType:
2103 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002104 this->finalizeReservedVertices();
2105 *extraVertexOffset = geoPoolState.fPoolStartVertex;
2106 vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002107 break;
2108 default:
2109 vbuf = NULL; // suppress warning
2110 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002111 }
2112
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002113 GrAssert(NULL != vbuf);
2114 GrAssert(!vbuf->isLocked());
2115 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002116 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002117 fHWGeometryState.fArrayPtrsDirty = true;
2118 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002119 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002120
2121 if (indexed) {
2122 GrAssert(NULL != extraIndexOffset);
2123
2124 GrGLIndexBuffer* ibuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002125 switch (this->getGeomSrc().fIndexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002126 case kBuffer_GeometrySrcType:
2127 *extraIndexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002128 ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002129 break;
2130 case kArray_GeometrySrcType:
2131 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002132 this->finalizeReservedIndices();
2133 *extraIndexOffset = geoPoolState.fPoolStartIndex;
2134 ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002135 break;
2136 default:
2137 ibuf = NULL; // suppress warning
2138 GrCrash("Unknown geometry src type!");
2139 }
2140
2141 GrAssert(NULL != ibuf);
2142 GrAssert(!ibuf->isLocked());
2143 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002144 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002145 fHWGeometryState.fIndexBuffer = ibuf;
2146 }
2147 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002148}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002149
2150int GrGpuGL::getMaxEdges() const {
2151 // FIXME: This is a pessimistic estimate based on how many other things
2152 // want to add uniforms. This should be centralized somewhere.
2153 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2154}
bsalomon@google.comfe676522011-06-17 18:12:21 +00002155