blob: fe51875bb9289cc950b30b7acdccaa574b131485 [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
reed@google.comac10a2d2010-12-22 21:39:39 +0000265GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000266
reed@google.comeeeb5a02010-12-23 15:12:59 +0000267 if (gPrintStartupSpew) {
268 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
269 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000270 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000271 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000272 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000273 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000274 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000275 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000276 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000277 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000278 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000279
280 GrGLClearErr();
281
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000282 resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000283
twiz@google.com0f31ca72011-03-18 17:38:11 +0000284 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000285 // check FS and fixed-function texture unit limits
286 // we only use textures in the fragment stage currently.
287 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000288 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
289 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
290 GrAssert(maxTextureUnits > kNumStages);
291 }
292 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
293 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
294 GrAssert(maxTextureUnits > kNumStages);
295 }
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000296 if (GR_GL_SUPPORT_ES2) {
297 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
298 &fMaxFragmentUniformVectors);
299 } else if (GR_GL_SUPPORT_DESKTOP) {
300 GrGLint max;
301 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
302 fMaxFragmentUniformVectors = max / 4;
303 } else {
304 fMaxFragmentUniformVectors = 16;
305 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000306
reed@google.comac10a2d2010-12-22 21:39:39 +0000307 ////////////////////////////////////////////////////////////////////////////
308 // Check for supported features.
309
310 int major, minor;
311 gl_version(&major, &minor);
312
twiz@google.com0f31ca72011-03-18 17:38:11 +0000313 GrGLint numFormats;
314 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000315 SkAutoSTMalloc<10, GrGLint> formats(numFormats);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000316 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000317 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000318 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000319 f8bitPaletteSupport = true;
320 break;
321 }
322 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000323
324 if (gPrintStartupSpew) {
325 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
326 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000327
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000328 GR_STATIC_ASSERT(0 == kNone_GrAALevel);
329 GR_STATIC_ASSERT(1 == kLow_GrAALevel);
330 GR_STATIC_ASSERT(2 == kMed_GrAALevel);
331 GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
reed@google.comac10a2d2010-12-22 21:39:39 +0000332
333 memset(fAASamples, 0, sizeof(fAASamples));
334 fMSFBOType = kNone_MSFBO;
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000335 if (GR_GL_SUPPORT_ES) {
336 if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000337 // chrome's extension is equivalent to the EXT msaa
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000338 // and fbo_blit extensions.
339 fMSFBOType = kDesktopEXT_MSFBO;
340 } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
341 fMSFBOType = kAppleES_MSFBO;
342 }
343 } else {
344 GrAssert(GR_GL_SUPPORT_DESKTOP);
345 if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
346 fMSFBOType = kDesktopARB_MSFBO;
347 } else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
348 has_gl_extension("GL_EXT_framebuffer_blit")) {
349 fMSFBOType = kDesktopEXT_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000350 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000351 }
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000352 if (gPrintStartupSpew) {
353 switch (fMSFBOType) {
354 case kNone_MSFBO:
355 GrPrintf("MSAA Support: NONE\n");
356 break;
357 case kDesktopARB_MSFBO:
358 GrPrintf("MSAA Support: DESKTOP ARB.\n");
359 break;
360 case kDesktopEXT_MSFBO:
361 GrPrintf("MSAA Support: DESKTOP EXT.\n");
362 break;
363 case kAppleES_MSFBO:
364 GrPrintf("MSAA Support: APPLE ES.\n");
365 break;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000366 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000367 }
368
369 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000370 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000371 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000372 if (maxSamples > 1 ) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000373 fAASamples[kNone_GrAALevel] = 0;
374 fAASamples[kLow_GrAALevel] = GrMax(2,
375 GrFixedFloorToInt((GR_FixedHalf) *
376 maxSamples));
377 fAASamples[kMed_GrAALevel] = GrMax(2,
378 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
379 maxSamples));
380 fAASamples[kHigh_GrAALevel] = maxSamples;
reed@google.comac10a2d2010-12-22 21:39:39 +0000381 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000382 if (gPrintStartupSpew) {
383 GrPrintf("\tMax Samples: %d\n", maxSamples);
384 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000385 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +0000386 fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000387
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000388 if (GR_GL_SUPPORT_DESKTOP) {
389 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
390 has_gl_extension("GL_EXT_stencil_wrap");
391 } else {
392 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
393 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000394 if (gPrintStartupSpew) {
395 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
396 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000397
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000398 if (GR_GL_SUPPORT_DESKTOP) {
399 // we could also look for GL_ATI_separate_stencil extension or
400 // GL_EXT_stencil_two_side but they use different function signatures
401 // than GL2.0+ (and than each other).
402 fTwoSidedStencilSupport = (major >= 2);
403 // supported on GL 1.4 and higher or by extension
404 fStencilWrapOpsSupport = (major > 1) ||
405 ((1 == major) && (minor >= 4)) ||
406 has_gl_extension("GL_EXT_stencil_wrap");
407 } else {
408 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
409 // an ES1 extension.
410 fTwoSidedStencilSupport = (major >= 2);
411 // stencil wrap support is in ES2, ES1 requires extension.
412 fStencilWrapOpsSupport = (major > 1) ||
413 has_gl_extension("GL_OES_stencil_wrap");
414 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000415 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000416 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
417 (fTwoSidedStencilSupport ? "YES" : "NO"),
418 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000419 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000420
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000421 if (GR_GL_SUPPORT_DESKTOP) {
422 fRGBA8Renderbuffer = true;
423 } else {
424 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
425 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000426 if (gPrintStartupSpew) {
427 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
428 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000429
430
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000431 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000432 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000433 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
434 }
435 }
436
437 if (GR_GL_SUPPORT_DESKTOP) {
438 fBufferLockSupport = true; // we require VBO support and the desktop VBO
439 // extension includes glMapBuffer.
440 } else {
441 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
442 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000443
reed@google.comeeeb5a02010-12-23 15:12:59 +0000444 if (gPrintStartupSpew) {
445 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
446 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000447
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000448 if (GR_GL_SUPPORT_DESKTOP) {
449 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
450 fNPOTTextureTileSupport = true;
451 fNPOTTextureSupport = true;
452 } else {
453 fNPOTTextureTileSupport = false;
454 fNPOTTextureSupport = false;
455 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000456 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000457 if (major >= 2) {
458 fNPOTTextureSupport = true;
459 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
460 } else {
461 fNPOTTextureSupport =
462 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
463 fNPOTTextureTileSupport = false;
464 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000465 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000466
bsalomon@google.com205d4602011-04-25 12:43:45 +0000467 fAALineSupport = GR_GL_SUPPORT_DESKTOP;
468
reed@google.comac10a2d2010-12-22 21:39:39 +0000469 ////////////////////////////////////////////////////////////////////////////
tomhudson@google.com747bf292011-06-14 18:16:52 +0000470 // Experiments to determine limitations that can't be queried.
471 // TODO: Make these a preprocess that generate some compile time constants.
472 // TODO: probe once at startup, rather than once per context creation.
reed@google.comac10a2d2010-12-22 21:39:39 +0000473
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000474 int expectNPOTTargets = GrGLGetGLInterface()->fNPOTRenderTargetSupport;
475 if (expectNPOTTargets == kProbe_GrGLCapability) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000476 fNPOTRenderTargetSupport =
477 probe_for_npot_render_target_support(fNPOTTextureSupport);
tomhudson@google.com30e4bb62011-06-15 19:41:46 +0000478 } else {
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000479 GrAssert(expectNPOTTargets == 0 || expectNPOTTargets == 1);
480 fNPOTRenderTargetSupport = static_cast<bool>(expectNPOTTargets);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000481 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000482
bsalomon@google.com0748f212011-02-01 22:56:16 +0000483 if (gPrintStartupSpew) {
484 if (fNPOTTextureSupport) {
485 GrPrintf("NPOT textures supported\n");
486 if (fNPOTTextureTileSupport) {
487 GrPrintf("NPOT texture tiling supported\n");
488 } else {
489 GrPrintf("NPOT texture tiling NOT supported\n");
490 }
491 if (fNPOTRenderTargetSupport) {
492 GrPrintf("NPOT render targets supported\n");
493 } else {
494 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000495 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000496 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000497 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000498 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000499 }
500
bsalomon@google.com91958362011-06-13 17:58:13 +0000501 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
502 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
tomhudson@google.com747bf292011-06-14 18:16:52 +0000503 // Our render targets are always created with textures as the color
bsalomon@google.com91958362011-06-13 17:58:13 +0000504 // attachment, hence this min:
505 fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000506
tomhudson@google.com747bf292011-06-14 18:16:52 +0000507 fMinRenderTargetHeight = GrGLGetGLInterface()->fMinRenderTargetHeight;
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000508 if (fMinRenderTargetHeight == kProbe_GrGLCapability) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000509 fMinRenderTargetHeight =
510 probe_for_min_render_target_height(fNPOTRenderTargetSupport,
511 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000512 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000513
tomhudson@google.com747bf292011-06-14 18:16:52 +0000514 fMinRenderTargetWidth = GrGLGetGLInterface()->fMinRenderTargetWidth;
tomhudson@google.come67bd3f2011-06-16 14:08:04 +0000515 if (fMinRenderTargetWidth == kProbe_GrGLCapability) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000516 fMinRenderTargetWidth =
517 probe_for_min_render_target_width(fNPOTRenderTargetSupport,
518 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000519 }
tomhudson@google.com747bf292011-06-14 18:16:52 +0000520
bsalomon@google.comfe676522011-06-17 18:12:21 +0000521 fLastSuccessfulStencilFmtIdx = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000522}
523
524GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000525}
526
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000527void GrGpuGL::resetContext() {
528 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000529 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000530 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000531
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000532 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000533 GR_GL(Disable(GR_GL_DEPTH_TEST));
534 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000535
twiz@google.com0f31ca72011-03-18 17:38:11 +0000536 GR_GL(Disable(GR_GL_CULL_FACE));
537 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000538 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000539
twiz@google.com0f31ca72011-03-18 17:38:11 +0000540 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000541 if (GR_GL_SUPPORT_DESKTOP) {
542 GR_GL(Disable(GR_GL_LINE_SMOOTH));
543 GR_GL(Disable(GR_GL_POINT_SMOOTH));
544 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000545 fHWAAState.fMSAAEnabled = false;
546 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000547 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000548
twiz@google.com0f31ca72011-03-18 17:38:11 +0000549 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000550 fHWDrawState.fFlagBits = 0;
551
reed@google.comac10a2d2010-12-22 21:39:39 +0000552 // we only ever use lines in hairline mode
553 GR_GL(LineWidth(1));
554
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000555 // invalid
556 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000557
reed@google.comac10a2d2010-12-22 21:39:39 +0000558 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000559 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
560 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000561
562 fHWDrawState.fBlendConstant = 0x00000000;
563 GR_GL(BlendColor(0,0,0,0));
564
reed@google.comac10a2d2010-12-22 21:39:39 +0000565 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000566
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000567 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000568
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000569 for (int s = 0; s < kNumStages; ++s) {
570 fHWDrawState.fTextures[s] = NULL;
571 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
572 -GR_ScalarMax,
573 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000574
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000575 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000576 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000577
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000578 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000579 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000580 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000581 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000582
bsalomon@google.comd302f142011-03-03 13:54:13 +0000583 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000584 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000585 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000586
587 fHWGeometryState.fIndexBuffer = NULL;
588 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000589
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000590 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000591
twiz@google.com0f31ca72011-03-18 17:38:11 +0000592 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000593 fHWDrawState.fRenderTarget = NULL;
594}
595
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000596GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
597
598 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
599 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
600 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
601 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
602
603 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
604 if (isRenderTarget) {
605 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
606 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
607 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
608 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
609 } else {
610 GrAssert(!isTexture); // this should have been filtered by GrContext
611 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
612 }
613 } else {
614 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
615 }
616 // we don't know what the RB ids are without glGets and we don't care
617 // since we aren't responsible for deleting them.
618 rtIDs.fStencilRenderbufferID = 0;
619 rtIDs.fMSColorRenderbufferID = 0;
620
621 rtIDs.fOwnIDs = false;
622 } else {
623 rtIDs.reset();
624 }
625
626 if (isTexture) {
627 GrGLTexture::GLTextureDesc texDesc;
628 GrGLenum dontCare;
629 if (!canBeTexture(desc.fConfig, &dontCare,
630 &texDesc.fUploadFormat,
631 &texDesc.fUploadType)) {
632 return NULL;
633 }
634
635 GrGLTexture::TexParams params;
636
637 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
638 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
639
bsalomon@google.com90405932011-06-17 15:56:55 +0000640 texDesc.fFormat = desc.fConfig;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000641 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
642 texDesc.fStencilBits = desc.fStencilBits;
643 texDesc.fTextureID = desc.fPlatformTexture;
644 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
645 texDesc.fOwnsID = false;
646
647 params.invalidate(); // rather than do glGets.
648
649 return new GrGLTexture(this, texDesc, rtIDs, params);
650 } else {
651 GrGLIRect viewport;
652 viewport.fLeft = 0;
653 viewport.fBottom = 0;
654 viewport.fWidth = desc.fWidth;
655 viewport.fHeight = desc.fHeight;
656
657 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
658 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
659 viewport, NULL);
660 }
661}
662
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000663GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000664
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000665 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000666
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000667 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000668 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
669 rtIDs.fMSColorRenderbufferID = 0;
670 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000671
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000672 GrGLIRect viewport;
673 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000674 GrGLuint stencilBits;
675 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000676
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000677 GrGLint samples;
678 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
679
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000680 rtIDs.fOwnIDs = false;
681
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000682 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
683 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000684}
685
bsalomon@google.com5782d712011-01-21 21:03:59 +0000686///////////////////////////////////////////////////////////////////////////////
687
twiz@google.com0f31ca72011-03-18 17:38:11 +0000688static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000689
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000690struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000691 GrGLenum fEnum;
692 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000693 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000694};
695
bsalomon@google.comfe676522011-06-17 18:12:21 +0000696const StencilFormat* GrGLStencilFormats(int* count) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000697 // defines stencil formats from more to less preferred
698 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000699 {GR_GL_STENCIL_INDEX8, 8, false},
700 {GR_GL_STENCIL_INDEX16, 16, false},
701 {GR_GL_DEPTH24_STENCIL8, 8, true },
702 {GR_GL_STENCIL_INDEX4, 4, false},
703 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
704 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000705 };
706
707 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000708 {GR_GL_STENCIL_INDEX8, 8, false},
709 {GR_GL_DEPTH24_STENCIL8, 8, true },
710 {GR_GL_STENCIL_INDEX4, 4, false},
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000711 };
712
713 if (GR_GL_SUPPORT_DESKTOP) {
bsalomon@google.comfe676522011-06-17 18:12:21 +0000714 *count = GR_ARRAY_COUNT(desktopStencilFormats);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000715 return desktopStencilFormats;
716 } else {
bsalomon@google.comfe676522011-06-17 18:12:21 +0000717 *count = GR_ARRAY_COUNT(esStencilFormats);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000718 return esStencilFormats;
719 }
720}
721
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000722// good to set a break-point here to know when createTexture fails
723static GrTexture* return_null_texture() {
724// GrAssert(!"null texture");
725 return NULL;
726}
727
728#if GR_DEBUG
729static size_t as_size_t(int x) {
730 return x;
731}
732#endif
733
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000734GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000735 const void* srcData,
736 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000737
738#if GR_COLLECT_STATS
739 ++fStats.fTextureCreateCnt;
740#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000741
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000742 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000743
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000744 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000745 GR_GL_NEAREST,
746 GR_GL_CLAMP_TO_EDGE,
747 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000748 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000749
reed@google.comac10a2d2010-12-22 21:39:39 +0000750 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000751 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000752
753 glDesc.fContentWidth = desc.fWidth;
754 glDesc.fContentHeight = desc.fHeight;
755 glDesc.fAllocWidth = desc.fWidth;
756 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000757 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000758 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000759 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000760
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000761 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000762 if (!canBeTexture(desc.fFormat,
763 &internalFormat,
764 &glDesc.fUploadFormat,
765 &glDesc.fUploadType)) {
766 return return_null_texture();
767 }
768
769 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000770 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000771 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000772 GrPrintf("AA RT requested but not supported on this platform.");
773 }
774
775 GR_GL(GenTextures(1, &glDesc.fTextureID));
776 if (!glDesc.fTextureID) {
777 return return_null_texture();
778 }
779
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000780 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000781
reed@google.com5e762232011-04-04 18:15:49 +0000782 // in case we need a temporary, trimmed copy of the src pixels
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000783 SkAutoSMalloc<128 * 128> trimStorage;
reed@google.com5e762232011-04-04 18:15:49 +0000784
reed@google.comac10a2d2010-12-22 21:39:39 +0000785 /*
786 * check if our srcData has extra bytes past each row. If so, we need
787 * to trim those off here, since GL doesn't let us pass the rowBytes as
788 * a parameter to glTexImage2D
789 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000790 if (GR_GL_SUPPORT_DESKTOP) {
791 if (srcData) {
792 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
793 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000794 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000795 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000796 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
797 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000798 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000799 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000800 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000801 char* dst = (char*)trimStorage.realloc(trimSize);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000802 for (int y = 0; y < desc.fHeight; y++) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000803 memcpy(dst, src, trimRowBytes);
804 src += rowBytes;
805 dst += trimRowBytes;
806 }
807 // now point srcData to our trimmed version
808 srcData = trimStorage.get();
809 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000810 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000811
reed@google.comac10a2d2010-12-22 21:39:39 +0000812 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000813 if (!this->npotRenderTargetSupport()) {
814 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
815 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
816 }
817
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000818 glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
819 glDesc.fAllocWidth);
820 glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
821 glDesc.fAllocHeight);
822 if (glDesc.fAllocWidth > fMaxRenderTargetSize ||
823 glDesc.fAllocHeight > fMaxRenderTargetSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000824 return return_null_texture();
825 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000826 } else if (!this->npotTextureSupport()) {
827 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
828 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000829 if (glDesc.fAllocWidth > fMaxTextureSize ||
830 glDesc.fAllocHeight > fMaxTextureSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000831 return return_null_texture();
832 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000833 }
834
twiz@google.com0f31ca72011-03-18 17:38:11 +0000835 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
836 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
837 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000838 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000839 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
840 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000841 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000842 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
843 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000844 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000845 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
846 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000847 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000848
twiz@google.com0f31ca72011-03-18 17:38:11 +0000849 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000850 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000851 supports8BitPalette()) {
852 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
853 GrAssert(desc.fWidth == glDesc.fAllocWidth);
854 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000855 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000856 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000857 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000858 glDesc.fAllocWidth, glDesc.fAllocHeight,
859 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000860 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000861 } else {
862 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
863 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000864 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000865 glDesc.fAllocWidth, glDesc.fAllocHeight,
866 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000867 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000868 desc.fHeight, glDesc.fUploadFormat,
869 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000870 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000871
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000872 int extraW = glDesc.fAllocWidth - desc.fWidth;
873 int extraH = glDesc.fAllocHeight - desc.fHeight;
874 int maxTexels = extraW * extraH;
reed@google.comac10a2d2010-12-22 21:39:39 +0000875 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
876 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
877
bsalomon@google.com3582bf92011-06-30 21:32:31 +0000878 SkAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
reed@google.comac10a2d2010-12-22 21:39:39 +0000879
880 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
881 if (extraH) {
882 uint8_t* lastRowStart = (uint8_t*) srcData +
883 (desc.fHeight - 1) * rowSize;
884 uint8_t* extraRowStart = (uint8_t*)texels.get();
885
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000886 for (int i = 0; i < extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000887 memcpy(extraRowStart, lastRowStart, rowSize);
888 extraRowStart += rowSize;
889 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000890 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000891 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
892 texels.get()));
893 }
894 if (extraW) {
895 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
896 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000897 for (int j = 0; j < desc.fHeight; ++j) {
898 for (int i = 0; i < extraW; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000899 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
900 extraTexel += glDesc.fUploadByteCount;
901 }
902 edgeTexel += rowSize;
903 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000904 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000905 desc.fHeight, glDesc.fUploadFormat,
906 glDesc.fUploadType, texels.get()));
907 }
908 if (extraW && extraH) {
909 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
910 - glDesc.fUploadByteCount;
911 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000912 for (int i = 0; i < extraW*extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000913 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
914 extraTexel += glDesc.fUploadByteCount;
915 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000916 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000917 extraW, extraH, glDesc.fUploadFormat,
918 glDesc.fUploadType, texels.get()));
919 }
920
921 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000922 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000923 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
924 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000925 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000926 }
927 }
928
929 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
930
931 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
932 rtIDs.fStencilRenderbufferID = 0;
933 rtIDs.fMSColorRenderbufferID = 0;
934 rtIDs.fRTFBOID = 0;
935 rtIDs.fTexFBOID = 0;
936 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000937 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000938
939 if (renderTarget) {
940#if GR_COLLECT_STATS
941 ++fStats.fRenderTargetCreateCnt;
942#endif
943 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000944 GrGLenum status;
945 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000946
947 // If need have both RT flag and srcData we have
948 // to invert the data before uploading because FBO
949 // will be rendered bottom up
950 GrAssert(NULL == srcData);
951 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
952
twiz@google.com59a190b2011-03-14 21:23:01 +0000953 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000954 GrAssert(rtIDs.fTexFBOID);
955
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000956 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000957 // to one and then resolve to the texture bound to the other.
958 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000959 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000960 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000961 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000962 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
963 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000964 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000965 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000966 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
967 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000968 return return_null_texture();
969 }
970 } else {
971 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
972 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000973 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000974 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000975 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000976 }
977
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000978 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000979 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000980 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000981 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000982
twiz@google.com0f31ca72011-03-18 17:38:11 +0000983 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000984
bsalomon@google.comfe676522011-06-17 18:12:21 +0000985 int stencilFmtCnt;
986 const StencilFormat* stencilFormats = NULL;
987 if (rtIDs.fStencilRenderbufferID) {
988 stencilFormats = GrGLStencilFormats(&stencilFmtCnt);
989 } else {
990 stencilFmtCnt = 1; // only 1 attempt when we don't need a stencil
991 }
992
993 for (int i = 0; i < stencilFmtCnt; ++i) {
994 // we start with the last stencil format that succeeded in hopes
995 // that we won't go through this loop more than once after the
996 // first (painful) stencil creation.
997 int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
998
reed@google.comac10a2d2010-12-22 21:39:39 +0000999 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001000 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001001 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001002 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001003 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001004 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001005 samples,
bsalomon@google.comfe676522011-06-17 18:12:21 +00001006 stencilFormats[sIdx].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +00001007 glDesc.fAllocWidth,
1008 glDesc.fAllocHeight));
1009 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001010 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
bsalomon@google.comfe676522011-06-17 18:12:21 +00001011 stencilFormats[sIdx].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +00001012 glDesc.fAllocWidth,
1013 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +00001014 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001015 err = GrGLGetGLInterface()->fGetError();
1016 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001017 continue;
1018 }
1019 }
1020 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
1021 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001022 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001023 rtIDs.fMSColorRenderbufferID));
1024 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001025 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001026 samples,
1027 msColorRenderbufferFormat,
1028 glDesc.fAllocWidth,
1029 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001030 err = GrGLGetGLInterface()->fGetError();
1031 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001032 continue;
1033 }
1034 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001035 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001036
1037#if GR_COLLECT_STATS
1038 ++fStats.fRenderTargetChngCnt;
1039#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001040 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1041 GR_GL_COLOR_ATTACHMENT0,
1042 GR_GL_TEXTURE_2D,
1043 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001044 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001045 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1046 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001047 continue;
1048 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001049 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001050 #if GR_COLLECT_STATS
1051 ++fStats.fRenderTargetChngCnt;
1052 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001053 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1054 GR_GL_COLOR_ATTACHMENT0,
1055 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001056 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001057
1058 }
1059 if (rtIDs.fStencilRenderbufferID) {
1060 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001061 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1062 GR_GL_STENCIL_ATTACHMENT,
1063 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001064 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001065 // if it is a packed format bind to depth also, otherwise
1066 // we may get an unsupported fbo completeness result
bsalomon@google.comfe676522011-06-17 18:12:21 +00001067 if (stencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001068 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1069 GR_GL_DEPTH_ATTACHMENT,
1070 GR_GL_RENDERBUFFER,
1071 rtIDs.fStencilRenderbufferID));
1072 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001073 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001074 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001075
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001076 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001077 // undo the depth bind
1078 if (rtIDs.fStencilRenderbufferID &&
bsalomon@google.comfe676522011-06-17 18:12:21 +00001079 stencilFormats[sIdx].fPacked) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001080 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1081 GR_GL_DEPTH_ATTACHMENT,
1082 GR_GL_RENDERBUFFER,
1083 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001084 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001085 continue;
1086 }
1087 // we're successful!
1088 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001089 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comfe676522011-06-17 18:12:21 +00001090 fLastSuccessfulStencilFmtIdx = sIdx;
1091 if (UNKNOWN_BITS == stencilFormats[sIdx].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001092 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001093 } else {
bsalomon@google.comfe676522011-06-17 18:12:21 +00001094 glDesc.fStencilBits = stencilFormats[sIdx].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001095 }
1096 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 break;
1098 }
1099 if (failed) {
1100 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001101 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001102 }
1103 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001104 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001105 }
1106 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001107 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001108 }
1109 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001110 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001111 }
1112 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1113 return return_null_texture();
1114 }
1115 }
1116#ifdef TRACE_TEXTURE_CREATION
1117 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1118 tex->fTextureID, width, height, tex->fUploadByteCount);
1119#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001120 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001121
1122 if (0 != rtIDs.fTexFBOID) {
1123 GrRenderTarget* rt = tex->asRenderTarget();
1124 // We've messed with FBO state but may not have set the correct viewport
1125 // so just dirty the rendertarget state to force a resend.
1126 fHWDrawState.fRenderTarget = NULL;
1127
1128 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001129 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001130 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1131 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001132 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001133 fCurrDrawState.fRenderTarget = rtSave;
1134 }
1135 }
1136 return tex;
1137}
1138
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001139GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001140 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001141 GR_GL(GenBuffers(1, &id));
1142 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001143 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001144 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001145 GrGLClearErr();
1146 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001147 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1148 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1149 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001150 GR_GL(DeleteBuffers(1, &id));
1151 // deleting bound buffer does implicit bind to 0
1152 fHWGeometryState.fVertexBuffer = NULL;
1153 return NULL;
1154 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001155 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 size, dynamic);
1157 fHWGeometryState.fVertexBuffer = vertexBuffer;
1158 return vertexBuffer;
1159 }
1160 return NULL;
1161}
1162
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001163GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001164 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001165 GR_GL(GenBuffers(1, &id));
1166 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001167 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
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_ELEMENT_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.fIndexBuffer = NULL;
1176 return NULL;
1177 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001178 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001179 size, dynamic);
1180 fHWGeometryState.fIndexBuffer = indexBuffer;
1181 return indexBuffer;
1182 }
1183 return NULL;
1184}
1185
reed@google.comac10a2d2010-12-22 21:39:39 +00001186void GrGpuGL::flushScissor(const GrIRect* rect) {
1187 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001188 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001189 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001190
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001191 GrGLIRect scissor;
1192 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001193 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001194 rect->width(), rect->height());
1195 if (scissor.contains(vp)) {
1196 rect = NULL;
1197 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001198 }
1199
1200 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001201 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001202 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001203 fHWBounds.fScissorRect = scissor;
1204 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001205 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001206 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001207 fHWBounds.fScissorEnabled = true;
1208 }
1209 } else {
1210 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001211 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001212 fHWBounds.fScissorEnabled = false;
1213 }
1214 }
1215}
1216
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001217void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001218 if (NULL == fCurrDrawState.fRenderTarget) {
1219 return;
1220 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001221 GrIRect r;
1222 if (NULL != rect) {
1223 // flushScissor expects rect to be clipped to the target.
1224 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001225 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1226 fCurrDrawState.fRenderTarget->height());
1227 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001228 rect = &r;
1229 } else {
1230 return;
1231 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001232 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001233 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001234 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001235 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001236 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001237 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1238 GrColorUnpackG(color)/255.f,
1239 GrColorUnpackB(color)/255.f,
1240 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001241 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001242}
1243
bsalomon@google.com398109c2011-04-14 18:40:27 +00001244void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001245 if (NULL == fCurrDrawState.fRenderTarget) {
1246 return;
1247 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001248
1249 this->flushRenderTarget(&GrIRect::EmptyIRect());
1250
reed@google.comac10a2d2010-12-22 21:39:39 +00001251 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001252 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001253 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001254 }
1255 GR_GL(StencilMask(mask));
1256 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001257 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001258 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001259}
1260
bsalomon@google.com398109c2011-04-14 18:40:27 +00001261void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001262 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001263#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001264 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001265 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001266 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001267#else
1268 // we could just clear the clip bit but when we go through
1269 // angle a partial stencil mask will cause clears to be
1270 // turned into draws. Our contract on GrDrawTarget says that
1271 // changing the clip between stencil passes may or may not
1272 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001273 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001274#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001275 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001276 flushScissor(&rect);
1277 GR_GL(StencilMask(clipStencilMask));
1278 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001279 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001280 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001281}
1282
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001283void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001284 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001285}
1286
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001287bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1288 int left, int top, int width, int height,
1289 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001290 GrGLenum internalFormat; // we don't use this for glReadPixels
1291 GrGLenum format;
1292 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001293 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1294 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001295 }
1296 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1297 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1298 switch (tgt->getResolveType()) {
1299 case GrGLRenderTarget::kCantResolve_ResolveType:
1300 return false;
1301 case GrGLRenderTarget::kAutoResolves_ResolveType:
1302 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1303 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001304 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001305 break;
1306 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001307 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001308 // we don't track the state of the READ FBO ID.
1309 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1310 break;
1311 default:
1312 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001313 }
1314
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001315 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001316
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001317 // the read rect is viewport-relative
1318 GrGLIRect readRect;
1319 readRect.setRelativeTo(glvp, left, top, width, height);
1320 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001321 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001322 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001323
1324 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1325 // API presents top-to-bottom
1326 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001327 size_t stride = width * GrBytesPerPixel(config);
bsalomon@google.com3582bf92011-06-30 21:32:31 +00001328 SkAutoMalloc rowStorage(stride);
reed@google.comac10a2d2010-12-22 21:39:39 +00001329 void* tmp = rowStorage.get();
1330
1331 const int halfY = height >> 1;
1332 char* top = reinterpret_cast<char*>(buffer);
1333 char* bottom = top + (height - 1) * stride;
1334 for (int y = 0; y < halfY; y++) {
1335 memcpy(tmp, top, stride);
1336 memcpy(top, bottom, stride);
1337 memcpy(bottom, tmp, stride);
1338 top += stride;
1339 bottom -= stride;
1340 }
1341 }
1342 return true;
1343}
1344
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001345void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001346
1347 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1348
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001349 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001350 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001351 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001352 #if GR_COLLECT_STATS
1353 ++fStats.fRenderTargetChngCnt;
1354 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001355 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001356 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1357 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001358 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001359 }
1360 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001361 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001362 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001363 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001364 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001365 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001366 fHWBounds.fViewportRect = vp;
1367 }
1368 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001369 if (NULL == bound || !bound->isEmpty()) {
1370 rt->flagAsNeedingResolve(bound);
1371 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001372}
1373
twiz@google.com0f31ca72011-03-18 17:38:11 +00001374GrGLenum gPrimitiveType2GLMode[] = {
1375 GR_GL_TRIANGLES,
1376 GR_GL_TRIANGLE_STRIP,
1377 GR_GL_TRIANGLE_FAN,
1378 GR_GL_POINTS,
1379 GR_GL_LINES,
1380 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001381};
1382
bsalomon@google.comd302f142011-03-03 13:54:13 +00001383#define SWAP_PER_DRAW 0
1384
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001385#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001386 #if GR_MAC_BUILD
1387 #include <AGL/agl.h>
1388 #elif GR_WIN32_BUILD
1389 void SwapBuf() {
1390 DWORD procID = GetCurrentProcessId();
1391 HWND hwnd = GetTopWindow(GetDesktopWindow());
1392 while(hwnd) {
1393 DWORD wndProcID = 0;
1394 GetWindowThreadProcessId(hwnd, &wndProcID);
1395 if(wndProcID == procID) {
1396 SwapBuffers(GetDC(hwnd));
1397 }
1398 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1399 }
1400 }
1401 #endif
1402#endif
1403
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001404void GrGpuGL::onGpuDrawIndexed(GrPrimitiveType type,
1405 uint32_t startVertex,
1406 uint32_t startIndex,
1407 uint32_t vertexCount,
1408 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001409 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1410
twiz@google.com0f31ca72011-03-18 17:38:11 +00001411 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001412
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001413 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1414 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1415
1416 // our setupGeometry better have adjusted this to zero since
1417 // DrawElements always draws from the begining of the arrays for idx 0.
1418 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001419
1420 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001421 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001422#if SWAP_PER_DRAW
1423 glFlush();
1424 #if GR_MAC_BUILD
1425 aglSwapBuffers(aglGetCurrentContext());
1426 int set_a_break_pt_here = 9;
1427 aglSwapBuffers(aglGetCurrentContext());
1428 #elif GR_WIN32_BUILD
1429 SwapBuf();
1430 int set_a_break_pt_here = 9;
1431 SwapBuf();
1432 #endif
1433#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001434}
1435
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001436void GrGpuGL::onGpuDrawNonIndexed(GrPrimitiveType type,
1437 uint32_t startVertex,
1438 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001439 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1440
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001441 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1442
1443 // our setupGeometry better have adjusted this to zero.
1444 // DrawElements doesn't take an offset so we always adjus the startVertex.
1445 GrAssert(0 == startVertex);
1446
1447 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1448 // account for startVertex in the DrawElements case. So we always
1449 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001450 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001451#if SWAP_PER_DRAW
1452 glFlush();
1453 #if GR_MAC_BUILD
1454 aglSwapBuffers(aglGetCurrentContext());
1455 int set_a_break_pt_here = 9;
1456 aglSwapBuffers(aglGetCurrentContext());
1457 #elif GR_WIN32_BUILD
1458 SwapBuf();
1459 int set_a_break_pt_here = 9;
1460 SwapBuf();
1461 #endif
1462#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001463}
1464
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001465void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001466
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001467 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001468 GrAssert(kNone_MSFBO != fMSFBOType);
1469 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001470 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001471 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001472 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001473 rt->textureFBOID()));
1474 #if GR_COLLECT_STATS
1475 ++fStats.fRenderTargetChngCnt;
1476 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001477 // make sure we go through flushRenderTarget() since we've modified
1478 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001479 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001480 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001481 const GrIRect dirtyRect = rt->getResolveRect();
1482 GrGLIRect r;
1483 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1484 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001485
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001486 if (kAppleES_MSFBO == fMSFBOType) {
1487 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001488 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001489 GR_GL(Scissor(r.fLeft, r.fBottom,
1490 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001491 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001492 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001493 fHWBounds.fScissorEnabled = true;
1494 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001495 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001496 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001497 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1498 flushScissor(NULL);
1499 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001500 int right = r.fLeft + r.fWidth;
1501 int top = r.fBottom + r.fHeight;
1502 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1503 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001504 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001505 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001506 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001507 }
1508}
1509
twiz@google.com0f31ca72011-03-18 17:38:11 +00001510static const GrGLenum grToGLStencilFunc[] = {
1511 GR_GL_ALWAYS, // kAlways_StencilFunc
1512 GR_GL_NEVER, // kNever_StencilFunc
1513 GR_GL_GREATER, // kGreater_StencilFunc
1514 GR_GL_GEQUAL, // kGEqual_StencilFunc
1515 GR_GL_LESS, // kLess_StencilFunc
1516 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1517 GR_GL_EQUAL, // kEqual_StencilFunc,
1518 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001519};
1520GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1521GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1522GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1523GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1524GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1525GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1526GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1527GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1528GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1529
twiz@google.com0f31ca72011-03-18 17:38:11 +00001530static const GrGLenum grToGLStencilOp[] = {
1531 GR_GL_KEEP, // kKeep_StencilOp
1532 GR_GL_REPLACE, // kReplace_StencilOp
1533 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1534 GR_GL_INCR, // kIncClamp_StencilOp
1535 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1536 GR_GL_DECR, // kDecClamp_StencilOp
1537 GR_GL_ZERO, // kZero_StencilOp
1538 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001539};
1540GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1541GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1542GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1543GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1544GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1545GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1546GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1547GR_STATIC_ASSERT(6 == kZero_StencilOp);
1548GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1549
reed@google.comac10a2d2010-12-22 21:39:39 +00001550void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001551 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001552
1553 // use stencil for clipping if clipping is enabled and the clip
1554 // has been written into the stencil.
1555 bool stencilClip = fClipState.fClipInStencil &&
1556 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001557 bool stencilChange = fHWStencilClip != stencilClip ||
1558 fHWDrawState.fStencilSettings != *settings ||
1559 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1560 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001561
1562 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001563
bsalomon@google.comd302f142011-03-03 13:54:13 +00001564 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1565 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001566
bsalomon@google.comd302f142011-03-03 13:54:13 +00001567 if (settings->isDisabled()) {
1568 if (stencilClip) {
1569 settings = &gClipStencilSettings;
1570 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001571 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001572
1573 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001574 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001575 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001576 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001577 #if GR_DEBUG
1578 if (!fStencilWrapOpsSupport) {
1579 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1580 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1581 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1582 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1583 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1584 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1585 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1586 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1587 }
1588 #endif
1589 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1590 GrAssert(stencilBits ||
1591 (GrStencilSettings::gDisabled ==
1592 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001593 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1594 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001595
1596 unsigned int frontRef = settings->fFrontFuncRef;
1597 unsigned int frontMask = settings->fFrontFuncMask;
1598 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001599 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001600
1601 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1602
1603 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1604 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1605 } else {
1606 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1607
1608 ConvertStencilFuncAndMask(settings->fFrontFunc,
1609 stencilClip,
1610 clipStencilMask,
1611 userStencilMask,
1612 &frontRef,
1613 &frontMask);
1614 frontWriteMask &= userStencilMask;
1615 }
1616 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001617 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001618 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001619 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001620 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001621 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001622 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001623 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001624 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001625 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001626
1627 unsigned int backRef = settings->fBackFuncRef;
1628 unsigned int backMask = settings->fBackFuncMask;
1629 unsigned int backWriteMask = settings->fBackWriteMask;
1630
1631
1632 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1633 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1634 backFunc = grToGLStencilFunc[settings->fBackFunc];
1635 } else {
1636 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1637 ConvertStencilFuncAndMask(settings->fBackFunc,
1638 stencilClip,
1639 clipStencilMask,
1640 userStencilMask,
1641 &backRef,
1642 &backMask);
1643 backWriteMask &= userStencilMask;
1644 }
1645
twiz@google.com0f31ca72011-03-18 17:38:11 +00001646 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1647 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1648 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1649 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1650 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001651 grToGLStencilOp[settings->fFrontPassOp],
1652 grToGLStencilOp[settings->fFrontPassOp]));
1653
twiz@google.com0f31ca72011-03-18 17:38:11 +00001654 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001655 grToGLStencilOp[settings->fBackPassOp],
1656 grToGLStencilOp[settings->fBackPassOp]));
1657 } else {
1658 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1659 GR_GL(StencilMask(frontWriteMask));
1660 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1661 grToGLStencilOp[settings->fFrontPassOp],
1662 grToGLStencilOp[settings->fFrontPassOp]));
1663 }
1664 }
1665 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001666 fHWStencilClip = stencilClip;
1667 }
1668}
1669
bsalomon@google.com0650e812011-04-08 18:07:53 +00001670bool GrGpuGL::useSmoothLines() {
1671 // there is a conflict between using smooth lines and our use of
1672 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1673 // but not in a premul-alpha way. So we only use them when our alpha
1674 // is 0xff.
1675
1676 // TODO: write a smarter line frag shader.
1677
1678 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1679 canDisableBlend();
1680}
1681
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001682void GrGpuGL::flushAAState(GrPrimitiveType type) {
1683 if (GR_GL_SUPPORT_DESKTOP) {
1684 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1685 // smooth lines.
1686
1687 // we prefer smooth lines over multisampled lines
1688 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001689 if (GrIsPrimTypeLines(type)) {
1690 bool smooth = useSmoothLines();
1691 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001692 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1693 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001694 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001695 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1696 fHWAAState.fSmoothLineEnabled = false;
1697 }
1698 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1699 fHWAAState.fMSAAEnabled) {
1700 GR_GL(Disable(GR_GL_MULTISAMPLE));
1701 fHWAAState.fMSAAEnabled = false;
1702 }
1703 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1704 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1705 fHWAAState.fMSAAEnabled) {
1706 if (fHWAAState.fMSAAEnabled) {
1707 GR_GL(Disable(GR_GL_MULTISAMPLE));
1708 fHWAAState.fMSAAEnabled = false;
1709 } else {
1710 GR_GL(Enable(GR_GL_MULTISAMPLE));
1711 fHWAAState.fMSAAEnabled = true;
1712 }
1713 }
1714 }
1715}
1716
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001717void GrGpuGL::flushBlend(GrPrimitiveType type,
1718 GrBlendCoeff srcCoeff,
1719 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001720 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1721 if (fHWBlendDisabled) {
1722 GR_GL(Enable(GR_GL_BLEND));
1723 fHWBlendDisabled = false;
1724 }
1725 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1726 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1727 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1728 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1729 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1730 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1731 }
1732 } else {
1733 bool blendOff = canDisableBlend();
1734 if (fHWBlendDisabled != blendOff) {
1735 if (blendOff) {
1736 GR_GL(Disable(GR_GL_BLEND));
1737 } else {
1738 GR_GL(Enable(GR_GL_BLEND));
1739 }
1740 fHWBlendDisabled = blendOff;
1741 }
1742 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001743 if (fHWDrawState.fSrcBlend != srcCoeff ||
1744 fHWDrawState.fDstBlend != dstCoeff) {
1745 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1746 gXfermodeCoeff2Blend[dstCoeff]));
1747 fHWDrawState.fSrcBlend = srcCoeff;
1748 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001749 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001750 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1751 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001752 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1753
1754 float c[] = {
1755 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1756 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1757 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1758 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1759 };
1760 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1761 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1762 }
1763 }
1764 }
1765}
1766
bsalomon@google.comffca4002011-02-22 20:34:01 +00001767bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001768
1769 // GrGpu::setupClipAndFlushState should have already checked this
1770 // and bailed if not true.
1771 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001772
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001773 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001774 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001775 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001776 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001777
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001778 // true for now, but maybe not with GrEffect.
1779 GrAssert(NULL != nextTexture);
1780 // if we created a rt/tex and rendered to it without using a
1781 // texture and now we're texuring from the rt it will still be
1782 // the last bound texture, but it needs resolving. So keep this
1783 // out of the "last != next" check.
1784 GrGLRenderTarget* texRT =
1785 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1786 if (NULL != texRT) {
1787 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001788 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001789
1790 if (fHWDrawState.fTextures[s] != nextTexture) {
1791 setTextureUnit(s);
1792 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1793 #if GR_COLLECT_STATS
1794 ++fStats.fTextureChngCnt;
1795 #endif
1796 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1797 fHWDrawState.fTextures[s] = nextTexture;
bsalomon@google.comcd19a5f2011-06-15 14:00:23 +00001798 // The texture matrix has to compensate for texture width/height
1799 // and NPOT-embedded-in-POT
1800 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001801 }
1802
1803 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1804 const GrGLTexture::TexParams& oldTexParams =
1805 nextTexture->getTexParams();
1806 GrGLTexture::TexParams newTexParams;
1807
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001808 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1809 newTexParams.fFilter = GR_GL_NEAREST;
1810 } else {
1811 newTexParams.fFilter = GR_GL_LINEAR;
1812 }
1813
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001814 newTexParams.fWrapS =
1815 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1816 newTexParams.fWrapT =
1817 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1818
1819 if (newTexParams.fFilter != oldTexParams.fFilter) {
1820 setTextureUnit(s);
1821 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1822 GR_GL_TEXTURE_MAG_FILTER,
1823 newTexParams.fFilter));
1824 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1825 GR_GL_TEXTURE_MIN_FILTER,
1826 newTexParams.fFilter));
1827 }
1828 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1829 setTextureUnit(s);
1830 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1831 GR_GL_TEXTURE_WRAP_S,
1832 newTexParams.fWrapS));
1833 }
1834 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1835 setTextureUnit(s);
1836 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1837 GR_GL_TEXTURE_WRAP_T,
1838 newTexParams.fWrapT));
1839 }
1840 nextTexture->setTexParams(newTexParams);
reed@google.comac10a2d2010-12-22 21:39:39 +00001841 }
1842 }
1843
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001844 GrIRect* rect = NULL;
1845 GrIRect clipBounds;
1846 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1847 fClip.hasConservativeBounds()) {
1848 fClip.getConservativeBounds().roundOut(&clipBounds);
1849 rect = &clipBounds;
1850 }
1851 this->flushRenderTarget(rect);
1852 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001853
reed@google.comac10a2d2010-12-22 21:39:39 +00001854 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1855 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1856 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001857 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001858 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001859 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001860 }
1861 }
1862
bsalomon@google.comd302f142011-03-03 13:54:13 +00001863 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1864 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001865 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001866 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001867 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001868 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001869 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001870 }
1871 GR_GL(ColorMask(mask, mask, mask, mask));
1872 }
1873
bsalomon@google.comd302f142011-03-03 13:54:13 +00001874 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1875 switch (fCurrDrawState.fDrawFace) {
1876 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001877 GR_GL(Enable(GR_GL_CULL_FACE));
1878 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001879 break;
1880 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001881 GR_GL(Enable(GR_GL_CULL_FACE));
1882 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001883 break;
1884 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001885 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001886 break;
1887 default:
1888 GrCrash("Unknown draw face.");
1889 }
1890 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1891 }
1892
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001893#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001894 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001895 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001896 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001897 NULL == fCurrDrawState.fRenderTarget ||
1898 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001899 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001900 fCurrDrawState.fRenderTarget);
1901 }
1902#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001903
reed@google.comac10a2d2010-12-22 21:39:39 +00001904 flushStencil();
1905
bsalomon@google.comd302f142011-03-03 13:54:13 +00001906 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001907 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001908 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001909}
1910
1911void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001912 if (fHWGeometryState.fVertexBuffer != buffer) {
1913 fHWGeometryState.fArrayPtrsDirty = true;
1914 fHWGeometryState.fVertexBuffer = buffer;
1915 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001916}
1917
1918void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001919 if (fHWGeometryState.fVertexBuffer == buffer) {
1920 // deleting bound buffer does implied bind to 0
1921 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001922 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001923 }
1924}
1925
1926void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001927 fHWGeometryState.fIndexBuffer = buffer;
reed@google.comac10a2d2010-12-22 21:39:39 +00001928}
1929
1930void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001931 if (fHWGeometryState.fIndexBuffer == buffer) {
1932 // deleting bound buffer does implied bind to 0
1933 fHWGeometryState.fIndexBuffer = NULL;
1934 }
1935}
1936
reed@google.comac10a2d2010-12-22 21:39:39 +00001937void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1938 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001939 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001940 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001941 }
1942 if (fHWDrawState.fRenderTarget == renderTarget) {
1943 fHWDrawState.fRenderTarget = NULL;
1944 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001945}
1946
1947void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001948 for (int s = 0; s < kNumStages; ++s) {
1949 if (fCurrDrawState.fTextures[s] == texture) {
1950 fCurrDrawState.fTextures[s] = NULL;
1951 }
1952 if (fHWDrawState.fTextures[s] == texture) {
1953 // deleting bound texture does implied bind to 0
1954 fHWDrawState.fTextures[s] = NULL;
1955 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001956 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001957}
1958
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001959bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001960 GrGLenum* internalFormat,
1961 GrGLenum* format,
1962 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001963 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001964 case kRGBA_8888_GrPixelConfig:
1965 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001966 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001967 if (GR_GL_SUPPORT_ES) {
1968 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1969 // format for a BGRA is BGRA not RGBA (as on desktop)
1970 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1971 } else {
1972 *internalFormat = GR_GL_RGBA;
1973 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001974 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001975 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001976 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001977 *format = GR_GL_RGB;
1978 *internalFormat = GR_GL_RGB;
1979 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001980 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001981 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001982 *format = GR_GL_RGBA;
1983 *internalFormat = GR_GL_RGBA;
1984 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001985 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001986 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001987 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001988 *format = GR_GL_PALETTE8_RGBA8;
1989 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001990 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001991 } else {
1992 return false;
1993 }
1994 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001995 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001996 *format = GR_GL_ALPHA;
1997 *internalFormat = GR_GL_ALPHA;
1998 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001999 break;
2000 default:
2001 return false;
2002 }
2003 return true;
2004}
2005
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002006void GrGpuGL::setTextureUnit(int unit) {
2007 GrAssert(unit >= 0 && unit < kNumStages);
2008 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002009 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002010 fActiveTextureUnitIdx = unit;
2011 }
2012}
bsalomon@google.com316f99232011-01-13 21:28:12 +00002013
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002014void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002015 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2016 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002017 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
2018 }
2019}
2020
reed@google.comac10a2d2010-12-22 21:39:39 +00002021/* On ES the internalFormat and format must match for TexImage and we use
2022 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
2023 decide the internalFormat. However, on ES internalFormat for
2024 RenderBufferStorage* has to be a specific format (not a base format like
2025 GL_RGBA).
2026 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002027bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002028 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002029 case kRGBA_8888_GrPixelConfig:
2030 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002031 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002032 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00002033 return true;
2034 } else {
2035 return false;
2036 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002037 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002038 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2039 // with FBO extension desktop GL has
2040 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002041 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002042 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002043 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002044 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002045 return true;
2046 default:
2047 return false;
2048 }
2049}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002050
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002051void GrGpuGL::resetDirtyFlags() {
2052 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2053}
2054
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002055void GrGpuGL::setBuffers(bool indexed,
2056 int* extraVertexOffset,
2057 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002058
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002059 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002060
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002061 const GeometryPoolState& geoPoolState = this->getGeomPoolState();
2062
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002063 GrGLVertexBuffer* vbuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002064 switch (this->getGeomSrc().fVertexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002065 case kBuffer_GeometrySrcType:
2066 *extraVertexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002067 vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002068 break;
2069 case kArray_GeometrySrcType:
2070 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002071 this->finalizeReservedVertices();
2072 *extraVertexOffset = geoPoolState.fPoolStartVertex;
2073 vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002074 break;
2075 default:
2076 vbuf = NULL; // suppress warning
2077 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002078 }
2079
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002080 GrAssert(NULL != vbuf);
2081 GrAssert(!vbuf->isLocked());
2082 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002083 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002084 fHWGeometryState.fArrayPtrsDirty = true;
2085 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002086 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002087
2088 if (indexed) {
2089 GrAssert(NULL != extraIndexOffset);
2090
2091 GrGLIndexBuffer* ibuf;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002092 switch (this->getGeomSrc().fIndexSrc) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002093 case kBuffer_GeometrySrcType:
2094 *extraIndexOffset = 0;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002095 ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002096 break;
2097 case kArray_GeometrySrcType:
2098 case kReserved_GeometrySrcType:
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00002099 this->finalizeReservedIndices();
2100 *extraIndexOffset = geoPoolState.fPoolStartIndex;
2101 ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002102 break;
2103 default:
2104 ibuf = NULL; // suppress warning
2105 GrCrash("Unknown geometry src type!");
2106 }
2107
2108 GrAssert(NULL != ibuf);
2109 GrAssert(!ibuf->isLocked());
2110 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002111 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002112 fHWGeometryState.fIndexBuffer = ibuf;
2113 }
2114 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002115}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002116
2117int GrGpuGL::getMaxEdges() const {
2118 // FIXME: This is a pessimistic estimate based on how many other things
2119 // want to add uniforms. This should be centralized somewhere.
2120 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2121}
bsalomon@google.comfe676522011-06-17 18:12:21 +00002122