blob: e40024a8378a2c164dea09f2d6cb449ae4dc09ef [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"
18#include "GrMemory.h"
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +000019#include "GrTypes.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);
315 GrAutoSTMalloc<10, GrGLint> formats(numFormats);
316 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
reed@google.comac10a2d2010-12-22 21:39:39 +0000521}
522
523GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000524}
525
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000526void GrGpuGL::resetContext() {
527 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000528 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000529 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000530
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000531 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000532 GR_GL(Disable(GR_GL_DEPTH_TEST));
533 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000534
twiz@google.com0f31ca72011-03-18 17:38:11 +0000535 GR_GL(Disable(GR_GL_CULL_FACE));
536 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000537 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000538
twiz@google.com0f31ca72011-03-18 17:38:11 +0000539 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000540 if (GR_GL_SUPPORT_DESKTOP) {
541 GR_GL(Disable(GR_GL_LINE_SMOOTH));
542 GR_GL(Disable(GR_GL_POINT_SMOOTH));
543 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000544 fHWAAState.fMSAAEnabled = false;
545 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000546 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000547
twiz@google.com0f31ca72011-03-18 17:38:11 +0000548 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000549 fHWDrawState.fFlagBits = 0;
550
reed@google.comac10a2d2010-12-22 21:39:39 +0000551 // we only ever use lines in hairline mode
552 GR_GL(LineWidth(1));
553
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000554 // invalid
555 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000556
reed@google.comac10a2d2010-12-22 21:39:39 +0000557 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000558 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
559 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000560
561 fHWDrawState.fBlendConstant = 0x00000000;
562 GR_GL(BlendColor(0,0,0,0));
563
reed@google.comac10a2d2010-12-22 21:39:39 +0000564 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000565
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000566 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000567
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000568 for (int s = 0; s < kNumStages; ++s) {
569 fHWDrawState.fTextures[s] = NULL;
570 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
571 -GR_ScalarMax,
572 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000573
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000574 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000575 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000576
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000577 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000578 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000579 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000580 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000581
bsalomon@google.comd302f142011-03-03 13:54:13 +0000582 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000583 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000584 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000585
586 fHWGeometryState.fIndexBuffer = NULL;
587 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000588
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000589 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000590
twiz@google.com0f31ca72011-03-18 17:38:11 +0000591 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000592 fHWDrawState.fRenderTarget = NULL;
593}
594
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000595GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
596
597 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
598 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
599 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
600 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
601
602 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
603 if (isRenderTarget) {
604 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
605 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
606 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
607 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
608 } else {
609 GrAssert(!isTexture); // this should have been filtered by GrContext
610 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
611 }
612 } else {
613 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
614 }
615 // we don't know what the RB ids are without glGets and we don't care
616 // since we aren't responsible for deleting them.
617 rtIDs.fStencilRenderbufferID = 0;
618 rtIDs.fMSColorRenderbufferID = 0;
619
620 rtIDs.fOwnIDs = false;
621 } else {
622 rtIDs.reset();
623 }
624
625 if (isTexture) {
626 GrGLTexture::GLTextureDesc texDesc;
627 GrGLenum dontCare;
628 if (!canBeTexture(desc.fConfig, &dontCare,
629 &texDesc.fUploadFormat,
630 &texDesc.fUploadType)) {
631 return NULL;
632 }
633
634 GrGLTexture::TexParams params;
635
636 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
637 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
638
639 texDesc.fFormat = texDesc.fFormat;
640 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
641 texDesc.fStencilBits = desc.fStencilBits;
642 texDesc.fTextureID = desc.fPlatformTexture;
643 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
644 texDesc.fOwnsID = false;
645
646 params.invalidate(); // rather than do glGets.
647
648 return new GrGLTexture(this, texDesc, rtIDs, params);
649 } else {
650 GrGLIRect viewport;
651 viewport.fLeft = 0;
652 viewport.fBottom = 0;
653 viewport.fWidth = desc.fWidth;
654 viewport.fHeight = desc.fHeight;
655
656 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
657 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
658 viewport, NULL);
659 }
660}
661
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000662GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000663
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000664 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000665
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000666 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000667 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
668 rtIDs.fMSColorRenderbufferID = 0;
669 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000670
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000671 GrGLIRect viewport;
672 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000673 GrGLuint stencilBits;
674 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000675
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000676 GrGLint samples;
677 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
678
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000679 rtIDs.fOwnIDs = false;
680
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000681 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
682 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000683}
684
bsalomon@google.com5782d712011-01-21 21:03:59 +0000685///////////////////////////////////////////////////////////////////////////////
686
twiz@google.com0f31ca72011-03-18 17:38:11 +0000687static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000688
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000689struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000690 GrGLenum fEnum;
691 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000692 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000693};
694
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000695const StencilFormat* GrGLStencilFormats() {
696 // defines stencil formats from more to less preferred
697 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000698 {GR_GL_STENCIL_INDEX8, 8, false},
699 {GR_GL_STENCIL_INDEX16, 16, false},
700 {GR_GL_DEPTH24_STENCIL8, 8, true },
701 {GR_GL_STENCIL_INDEX4, 4, false},
702 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
703 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
704 {0, 0, false}
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},
711 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000712 };
713
714 if (GR_GL_SUPPORT_DESKTOP) {
715 return desktopStencilFormats;
716 } else {
717 return esStencilFormats;
718 }
719}
720
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000721// good to set a break-point here to know when createTexture fails
722static GrTexture* return_null_texture() {
723// GrAssert(!"null texture");
724 return NULL;
725}
726
727#if GR_DEBUG
728static size_t as_size_t(int x) {
729 return x;
730}
731#endif
732
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000733GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000734 const void* srcData,
735 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000736
737#if GR_COLLECT_STATS
738 ++fStats.fTextureCreateCnt;
739#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000740
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000741 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000742
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000743 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000744 GR_GL_NEAREST,
745 GR_GL_CLAMP_TO_EDGE,
746 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000747 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000748
reed@google.comac10a2d2010-12-22 21:39:39 +0000749 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000750 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000751
752 glDesc.fContentWidth = desc.fWidth;
753 glDesc.fContentHeight = desc.fHeight;
754 glDesc.fAllocWidth = desc.fWidth;
755 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000756 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000757 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000758 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000759
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000760 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000761 if (!canBeTexture(desc.fFormat,
762 &internalFormat,
763 &glDesc.fUploadFormat,
764 &glDesc.fUploadType)) {
765 return return_null_texture();
766 }
767
768 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000769 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000770 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000771 GrPrintf("AA RT requested but not supported on this platform.");
772 }
773
774 GR_GL(GenTextures(1, &glDesc.fTextureID));
775 if (!glDesc.fTextureID) {
776 return return_null_texture();
777 }
778
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000779 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000780
reed@google.com5e762232011-04-04 18:15:49 +0000781 // in case we need a temporary, trimmed copy of the src pixels
782 GrAutoSMalloc<128 * 128> trimStorage;
783
reed@google.comac10a2d2010-12-22 21:39:39 +0000784 /*
785 * check if our srcData has extra bytes past each row. If so, we need
786 * to trim those off here, since GL doesn't let us pass the rowBytes as
787 * a parameter to glTexImage2D
788 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000789 if (GR_GL_SUPPORT_DESKTOP) {
790 if (srcData) {
791 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
792 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000793 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000794 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000795 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
796 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000797 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000798 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000799 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000800 char* dst = (char*)trimStorage.realloc(trimSize);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000801 for (int y = 0; y < desc.fHeight; y++) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000802 memcpy(dst, src, trimRowBytes);
803 src += rowBytes;
804 dst += trimRowBytes;
805 }
806 // now point srcData to our trimmed version
807 srcData = trimStorage.get();
808 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000809 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000810
reed@google.comac10a2d2010-12-22 21:39:39 +0000811 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000812 if (!this->npotRenderTargetSupport()) {
813 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
814 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
815 }
816
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000817 glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
818 glDesc.fAllocWidth);
819 glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
820 glDesc.fAllocHeight);
821 if (glDesc.fAllocWidth > fMaxRenderTargetSize ||
822 glDesc.fAllocHeight > fMaxRenderTargetSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000823 return return_null_texture();
824 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000825 } else if (!this->npotTextureSupport()) {
826 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
827 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000828 if (glDesc.fAllocWidth > fMaxTextureSize ||
829 glDesc.fAllocHeight > fMaxTextureSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000830 return return_null_texture();
831 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000832 }
833
twiz@google.com0f31ca72011-03-18 17:38:11 +0000834 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
835 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
836 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000837 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000838 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
839 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000840 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000841 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
842 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000843 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000844 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
845 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000846 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000847
twiz@google.com0f31ca72011-03-18 17:38:11 +0000848 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000849 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000850 supports8BitPalette()) {
851 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
852 GrAssert(desc.fWidth == glDesc.fAllocWidth);
853 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000854 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000855 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000856 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000857 glDesc.fAllocWidth, glDesc.fAllocHeight,
858 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000859 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000860 } else {
861 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
862 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000863 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000864 glDesc.fAllocWidth, glDesc.fAllocHeight,
865 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000866 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000867 desc.fHeight, glDesc.fUploadFormat,
868 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000869 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000870
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000871 int extraW = glDesc.fAllocWidth - desc.fWidth;
872 int extraH = glDesc.fAllocHeight - desc.fHeight;
873 int maxTexels = extraW * extraH;
reed@google.comac10a2d2010-12-22 21:39:39 +0000874 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
875 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
876
877 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
878
879 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
880 if (extraH) {
881 uint8_t* lastRowStart = (uint8_t*) srcData +
882 (desc.fHeight - 1) * rowSize;
883 uint8_t* extraRowStart = (uint8_t*)texels.get();
884
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000885 for (int i = 0; i < extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000886 memcpy(extraRowStart, lastRowStart, rowSize);
887 extraRowStart += rowSize;
888 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000889 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000890 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
891 texels.get()));
892 }
893 if (extraW) {
894 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
895 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000896 for (int j = 0; j < desc.fHeight; ++j) {
897 for (int i = 0; i < extraW; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000898 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
899 extraTexel += glDesc.fUploadByteCount;
900 }
901 edgeTexel += rowSize;
902 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000903 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000904 desc.fHeight, glDesc.fUploadFormat,
905 glDesc.fUploadType, texels.get()));
906 }
907 if (extraW && extraH) {
908 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
909 - glDesc.fUploadByteCount;
910 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000911 for (int i = 0; i < extraW*extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000912 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
913 extraTexel += glDesc.fUploadByteCount;
914 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000915 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000916 extraW, extraH, glDesc.fUploadFormat,
917 glDesc.fUploadType, texels.get()));
918 }
919
920 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000921 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
923 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000924 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000925 }
926 }
927
928 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
929
930 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
931 rtIDs.fStencilRenderbufferID = 0;
932 rtIDs.fMSColorRenderbufferID = 0;
933 rtIDs.fRTFBOID = 0;
934 rtIDs.fTexFBOID = 0;
935 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000936 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000937
938 if (renderTarget) {
939#if GR_COLLECT_STATS
940 ++fStats.fRenderTargetCreateCnt;
941#endif
942 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000943 GrGLenum status;
944 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000945
946 // If need have both RT flag and srcData we have
947 // to invert the data before uploading because FBO
948 // will be rendered bottom up
949 GrAssert(NULL == srcData);
950 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
951
twiz@google.com59a190b2011-03-14 21:23:01 +0000952 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000953 GrAssert(rtIDs.fTexFBOID);
954
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000955 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000956 // to one and then resolve to the texture bound to the other.
957 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000958 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000959 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000960 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000961 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
962 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000963 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000964 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000965 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
966 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000967 return return_null_texture();
968 }
969 } else {
970 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
971 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000972 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000973 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000974 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000975 }
976
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000977 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000978 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000979 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000980 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000981
twiz@google.com0f31ca72011-03-18 17:38:11 +0000982 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000983
984 const StencilFormat* stencilFormats = GrGLStencilFormats();
985 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000986 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000987 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000988 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000989 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000990 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000991 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000992 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000993 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000994 glDesc.fAllocWidth,
995 glDesc.fAllocHeight));
996 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000997 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000998 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000999 glDesc.fAllocWidth,
1000 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +00001001 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001002 err = GrGLGetGLInterface()->fGetError();
1003 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001004 continue;
1005 }
1006 }
1007 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
1008 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001009 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001010 rtIDs.fMSColorRenderbufferID));
1011 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001012 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001013 samples,
1014 msColorRenderbufferFormat,
1015 glDesc.fAllocWidth,
1016 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001017 err = GrGLGetGLInterface()->fGetError();
1018 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001019 continue;
1020 }
1021 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001022 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001023
1024#if GR_COLLECT_STATS
1025 ++fStats.fRenderTargetChngCnt;
1026#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001027 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1028 GR_GL_COLOR_ATTACHMENT0,
1029 GR_GL_TEXTURE_2D,
1030 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001031 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001032 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1033 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001034 continue;
1035 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001036 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001037 #if GR_COLLECT_STATS
1038 ++fStats.fRenderTargetChngCnt;
1039 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001040 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1041 GR_GL_COLOR_ATTACHMENT0,
1042 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001043 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001044
1045 }
1046 if (rtIDs.fStencilRenderbufferID) {
1047 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001048 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1049 GR_GL_STENCIL_ATTACHMENT,
1050 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001051 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001052 // if it is a packed format bind to depth also, otherwise
1053 // we may get an unsupported fbo completeness result
1054 if (stencilFormats[i].fPacked) {
1055 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1056 GR_GL_DEPTH_ATTACHMENT,
1057 GR_GL_RENDERBUFFER,
1058 rtIDs.fStencilRenderbufferID));
1059 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001060 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001061 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001062
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001063 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001064 // undo the depth bind
1065 if (rtIDs.fStencilRenderbufferID &&
1066 stencilFormats[i].fPacked) {
1067 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1068 GR_GL_DEPTH_ATTACHMENT,
1069 GR_GL_RENDERBUFFER,
1070 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001071 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001072 continue;
1073 }
1074 // we're successful!
1075 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001076 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001077 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001078 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001079 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001080 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001081 }
1082 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001083 break;
1084 }
1085 if (failed) {
1086 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001087 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 }
1089 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001090 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001091 }
1092 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001093 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 }
1095 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001096 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 }
1098 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1099 return return_null_texture();
1100 }
1101 }
1102#ifdef TRACE_TEXTURE_CREATION
1103 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1104 tex->fTextureID, width, height, tex->fUploadByteCount);
1105#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001106 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001107
1108 if (0 != rtIDs.fTexFBOID) {
1109 GrRenderTarget* rt = tex->asRenderTarget();
1110 // We've messed with FBO state but may not have set the correct viewport
1111 // so just dirty the rendertarget state to force a resend.
1112 fHWDrawState.fRenderTarget = NULL;
1113
1114 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001115 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001116 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1117 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001118 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001119 fCurrDrawState.fRenderTarget = rtSave;
1120 }
1121 }
1122 return tex;
1123}
1124
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001125GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001126 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001127 GR_GL(GenBuffers(1, &id));
1128 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001129 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001130 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001131 GrGLClearErr();
1132 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001133 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1134 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1135 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001136 GR_GL(DeleteBuffers(1, &id));
1137 // deleting bound buffer does implicit bind to 0
1138 fHWGeometryState.fVertexBuffer = NULL;
1139 return NULL;
1140 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001141 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001142 size, dynamic);
1143 fHWGeometryState.fVertexBuffer = vertexBuffer;
1144 return vertexBuffer;
1145 }
1146 return NULL;
1147}
1148
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001149GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001150 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001151 GR_GL(GenBuffers(1, &id));
1152 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001153 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001154 GrGLClearErr();
1155 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001156 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1157 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1158 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001159 GR_GL(DeleteBuffers(1, &id));
1160 // deleting bound buffer does implicit bind to 0
1161 fHWGeometryState.fIndexBuffer = NULL;
1162 return NULL;
1163 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001164 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001165 size, dynamic);
1166 fHWGeometryState.fIndexBuffer = indexBuffer;
1167 return indexBuffer;
1168 }
1169 return NULL;
1170}
1171
reed@google.comac10a2d2010-12-22 21:39:39 +00001172void GrGpuGL::flushScissor(const GrIRect* rect) {
1173 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001174 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001175 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001176
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001177 GrGLIRect scissor;
1178 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001179 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001180 rect->width(), rect->height());
1181 if (scissor.contains(vp)) {
1182 rect = NULL;
1183 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001184 }
1185
1186 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001187 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001188 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001189 fHWBounds.fScissorRect = scissor;
1190 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001191 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001192 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001193 fHWBounds.fScissorEnabled = true;
1194 }
1195 } else {
1196 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001197 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001198 fHWBounds.fScissorEnabled = false;
1199 }
1200 }
1201}
1202
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001203void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001204 if (NULL == fCurrDrawState.fRenderTarget) {
1205 return;
1206 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001207 GrIRect r;
1208 if (NULL != rect) {
1209 // flushScissor expects rect to be clipped to the target.
1210 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001211 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1212 fCurrDrawState.fRenderTarget->height());
1213 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001214 rect = &r;
1215 } else {
1216 return;
1217 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001218 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001219 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001220 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001221 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001222 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001223 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1224 GrColorUnpackG(color)/255.f,
1225 GrColorUnpackB(color)/255.f,
1226 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001227 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001228}
1229
bsalomon@google.com398109c2011-04-14 18:40:27 +00001230void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001231 if (NULL == fCurrDrawState.fRenderTarget) {
1232 return;
1233 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001234
1235 this->flushRenderTarget(&GrIRect::EmptyIRect());
1236
reed@google.comac10a2d2010-12-22 21:39:39 +00001237 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001238 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001239 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001240 }
1241 GR_GL(StencilMask(mask));
1242 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001243 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001244 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001245}
1246
bsalomon@google.com398109c2011-04-14 18:40:27 +00001247void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001248 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001249#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001250 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001251 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001252 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001253#else
1254 // we could just clear the clip bit but when we go through
1255 // angle a partial stencil mask will cause clears to be
1256 // turned into draws. Our contract on GrDrawTarget says that
1257 // changing the clip between stencil passes may or may not
1258 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001259 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001260#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001261 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001262 flushScissor(&rect);
1263 GR_GL(StencilMask(clipStencilMask));
1264 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001265 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001266 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001267}
1268
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001269void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001270 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001271}
1272
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001273bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1274 int left, int top, int width, int height,
1275 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001276 GrGLenum internalFormat; // we don't use this for glReadPixels
1277 GrGLenum format;
1278 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001279 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1280 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001281 }
1282 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1283 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1284 switch (tgt->getResolveType()) {
1285 case GrGLRenderTarget::kCantResolve_ResolveType:
1286 return false;
1287 case GrGLRenderTarget::kAutoResolves_ResolveType:
1288 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1289 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001290 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001291 break;
1292 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001293 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001294 // we don't track the state of the READ FBO ID.
1295 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1296 break;
1297 default:
1298 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001299 }
1300
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001301 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001302
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001303 // the read rect is viewport-relative
1304 GrGLIRect readRect;
1305 readRect.setRelativeTo(glvp, left, top, width, height);
1306 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001307 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001308 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001309
1310 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1311 // API presents top-to-bottom
1312 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001313 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001314 GrAutoMalloc rowStorage(stride);
1315 void* tmp = rowStorage.get();
1316
1317 const int halfY = height >> 1;
1318 char* top = reinterpret_cast<char*>(buffer);
1319 char* bottom = top + (height - 1) * stride;
1320 for (int y = 0; y < halfY; y++) {
1321 memcpy(tmp, top, stride);
1322 memcpy(top, bottom, stride);
1323 memcpy(bottom, tmp, stride);
1324 top += stride;
1325 bottom -= stride;
1326 }
1327 }
1328 return true;
1329}
1330
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001331void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001332
1333 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1334
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001335 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001336 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001337 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001338 #if GR_COLLECT_STATS
1339 ++fStats.fRenderTargetChngCnt;
1340 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001341 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001342 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1343 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001344 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001345 }
1346 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001347 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001348 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001349 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001350 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001351 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001352 fHWBounds.fViewportRect = vp;
1353 }
1354 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001355 if (NULL == bound || !bound->isEmpty()) {
1356 rt->flagAsNeedingResolve(bound);
1357 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001358}
1359
twiz@google.com0f31ca72011-03-18 17:38:11 +00001360GrGLenum gPrimitiveType2GLMode[] = {
1361 GR_GL_TRIANGLES,
1362 GR_GL_TRIANGLE_STRIP,
1363 GR_GL_TRIANGLE_FAN,
1364 GR_GL_POINTS,
1365 GR_GL_LINES,
1366 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001367};
1368
bsalomon@google.comd302f142011-03-03 13:54:13 +00001369#define SWAP_PER_DRAW 0
1370
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001371#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001372 #if GR_MAC_BUILD
1373 #include <AGL/agl.h>
1374 #elif GR_WIN32_BUILD
1375 void SwapBuf() {
1376 DWORD procID = GetCurrentProcessId();
1377 HWND hwnd = GetTopWindow(GetDesktopWindow());
1378 while(hwnd) {
1379 DWORD wndProcID = 0;
1380 GetWindowThreadProcessId(hwnd, &wndProcID);
1381 if(wndProcID == procID) {
1382 SwapBuffers(GetDC(hwnd));
1383 }
1384 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1385 }
1386 }
1387 #endif
1388#endif
1389
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001390void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1391 uint32_t startVertex,
1392 uint32_t startIndex,
1393 uint32_t vertexCount,
1394 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001395 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1396
twiz@google.com0f31ca72011-03-18 17:38:11 +00001397 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001398
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001399 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1400 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1401
1402 // our setupGeometry better have adjusted this to zero since
1403 // DrawElements always draws from the begining of the arrays for idx 0.
1404 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001405
1406 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001407 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001408#if SWAP_PER_DRAW
1409 glFlush();
1410 #if GR_MAC_BUILD
1411 aglSwapBuffers(aglGetCurrentContext());
1412 int set_a_break_pt_here = 9;
1413 aglSwapBuffers(aglGetCurrentContext());
1414 #elif GR_WIN32_BUILD
1415 SwapBuf();
1416 int set_a_break_pt_here = 9;
1417 SwapBuf();
1418 #endif
1419#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001420}
1421
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001422void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1423 uint32_t startVertex,
1424 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001425 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1426
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001427 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1428
1429 // our setupGeometry better have adjusted this to zero.
1430 // DrawElements doesn't take an offset so we always adjus the startVertex.
1431 GrAssert(0 == startVertex);
1432
1433 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1434 // account for startVertex in the DrawElements case. So we always
1435 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001436 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001437#if SWAP_PER_DRAW
1438 glFlush();
1439 #if GR_MAC_BUILD
1440 aglSwapBuffers(aglGetCurrentContext());
1441 int set_a_break_pt_here = 9;
1442 aglSwapBuffers(aglGetCurrentContext());
1443 #elif GR_WIN32_BUILD
1444 SwapBuf();
1445 int set_a_break_pt_here = 9;
1446 SwapBuf();
1447 #endif
1448#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001449}
1450
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001451void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001452
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001453 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001454 GrAssert(kNone_MSFBO != fMSFBOType);
1455 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001456 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001457 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001458 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001459 rt->textureFBOID()));
1460 #if GR_COLLECT_STATS
1461 ++fStats.fRenderTargetChngCnt;
1462 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001463 // make sure we go through flushRenderTarget() since we've modified
1464 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001465 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001466 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001467 const GrIRect dirtyRect = rt->getResolveRect();
1468 GrGLIRect r;
1469 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1470 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001471
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001472 if (kAppleES_MSFBO == fMSFBOType) {
1473 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001474 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001475 GR_GL(Scissor(r.fLeft, r.fBottom,
1476 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001477 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001478 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001479 fHWBounds.fScissorEnabled = true;
1480 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001481 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001482 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001483 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1484 flushScissor(NULL);
1485 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001486 int right = r.fLeft + r.fWidth;
1487 int top = r.fBottom + r.fHeight;
1488 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1489 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001490 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001491 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001492 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001493 }
1494}
1495
twiz@google.com0f31ca72011-03-18 17:38:11 +00001496static const GrGLenum grToGLStencilFunc[] = {
1497 GR_GL_ALWAYS, // kAlways_StencilFunc
1498 GR_GL_NEVER, // kNever_StencilFunc
1499 GR_GL_GREATER, // kGreater_StencilFunc
1500 GR_GL_GEQUAL, // kGEqual_StencilFunc
1501 GR_GL_LESS, // kLess_StencilFunc
1502 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1503 GR_GL_EQUAL, // kEqual_StencilFunc,
1504 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001505};
1506GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1507GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1508GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1509GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1510GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1511GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1512GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1513GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1514GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1515
twiz@google.com0f31ca72011-03-18 17:38:11 +00001516static const GrGLenum grToGLStencilOp[] = {
1517 GR_GL_KEEP, // kKeep_StencilOp
1518 GR_GL_REPLACE, // kReplace_StencilOp
1519 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1520 GR_GL_INCR, // kIncClamp_StencilOp
1521 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1522 GR_GL_DECR, // kDecClamp_StencilOp
1523 GR_GL_ZERO, // kZero_StencilOp
1524 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001525};
1526GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1527GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1528GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1529GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1530GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1531GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1532GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1533GR_STATIC_ASSERT(6 == kZero_StencilOp);
1534GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1535
reed@google.comac10a2d2010-12-22 21:39:39 +00001536void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001537 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001538
1539 // use stencil for clipping if clipping is enabled and the clip
1540 // has been written into the stencil.
1541 bool stencilClip = fClipState.fClipInStencil &&
1542 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001543 bool stencilChange = fHWStencilClip != stencilClip ||
1544 fHWDrawState.fStencilSettings != *settings ||
1545 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1546 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001547
1548 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001549
bsalomon@google.comd302f142011-03-03 13:54:13 +00001550 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1551 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001552
bsalomon@google.comd302f142011-03-03 13:54:13 +00001553 if (settings->isDisabled()) {
1554 if (stencilClip) {
1555 settings = &gClipStencilSettings;
1556 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001557 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001558
1559 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001560 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001561 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001562 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001563 #if GR_DEBUG
1564 if (!fStencilWrapOpsSupport) {
1565 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1566 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1567 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1568 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1569 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1570 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1571 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1572 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1573 }
1574 #endif
1575 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1576 GrAssert(stencilBits ||
1577 (GrStencilSettings::gDisabled ==
1578 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001579 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1580 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001581
1582 unsigned int frontRef = settings->fFrontFuncRef;
1583 unsigned int frontMask = settings->fFrontFuncMask;
1584 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001585 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001586
1587 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1588
1589 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1590 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1591 } else {
1592 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1593
1594 ConvertStencilFuncAndMask(settings->fFrontFunc,
1595 stencilClip,
1596 clipStencilMask,
1597 userStencilMask,
1598 &frontRef,
1599 &frontMask);
1600 frontWriteMask &= userStencilMask;
1601 }
1602 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001603 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001604 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001605 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001606 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001607 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001608 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001609 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001610 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001611 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001612
1613 unsigned int backRef = settings->fBackFuncRef;
1614 unsigned int backMask = settings->fBackFuncMask;
1615 unsigned int backWriteMask = settings->fBackWriteMask;
1616
1617
1618 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1619 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1620 backFunc = grToGLStencilFunc[settings->fBackFunc];
1621 } else {
1622 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1623 ConvertStencilFuncAndMask(settings->fBackFunc,
1624 stencilClip,
1625 clipStencilMask,
1626 userStencilMask,
1627 &backRef,
1628 &backMask);
1629 backWriteMask &= userStencilMask;
1630 }
1631
twiz@google.com0f31ca72011-03-18 17:38:11 +00001632 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1633 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1634 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1635 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1636 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001637 grToGLStencilOp[settings->fFrontPassOp],
1638 grToGLStencilOp[settings->fFrontPassOp]));
1639
twiz@google.com0f31ca72011-03-18 17:38:11 +00001640 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001641 grToGLStencilOp[settings->fBackPassOp],
1642 grToGLStencilOp[settings->fBackPassOp]));
1643 } else {
1644 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1645 GR_GL(StencilMask(frontWriteMask));
1646 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1647 grToGLStencilOp[settings->fFrontPassOp],
1648 grToGLStencilOp[settings->fFrontPassOp]));
1649 }
1650 }
1651 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001652 fHWStencilClip = stencilClip;
1653 }
1654}
1655
bsalomon@google.com0650e812011-04-08 18:07:53 +00001656bool GrGpuGL::useSmoothLines() {
1657 // there is a conflict between using smooth lines and our use of
1658 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1659 // but not in a premul-alpha way. So we only use them when our alpha
1660 // is 0xff.
1661
1662 // TODO: write a smarter line frag shader.
1663
1664 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1665 canDisableBlend();
1666}
1667
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001668void GrGpuGL::flushAAState(GrPrimitiveType type) {
1669 if (GR_GL_SUPPORT_DESKTOP) {
1670 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1671 // smooth lines.
1672
1673 // we prefer smooth lines over multisampled lines
1674 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001675 if (GrIsPrimTypeLines(type)) {
1676 bool smooth = useSmoothLines();
1677 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001678 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1679 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001680 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001681 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1682 fHWAAState.fSmoothLineEnabled = false;
1683 }
1684 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1685 fHWAAState.fMSAAEnabled) {
1686 GR_GL(Disable(GR_GL_MULTISAMPLE));
1687 fHWAAState.fMSAAEnabled = false;
1688 }
1689 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1690 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1691 fHWAAState.fMSAAEnabled) {
1692 if (fHWAAState.fMSAAEnabled) {
1693 GR_GL(Disable(GR_GL_MULTISAMPLE));
1694 fHWAAState.fMSAAEnabled = false;
1695 } else {
1696 GR_GL(Enable(GR_GL_MULTISAMPLE));
1697 fHWAAState.fMSAAEnabled = true;
1698 }
1699 }
1700 }
1701}
1702
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001703void GrGpuGL::flushBlend(GrPrimitiveType type,
1704 GrBlendCoeff srcCoeff,
1705 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001706 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1707 if (fHWBlendDisabled) {
1708 GR_GL(Enable(GR_GL_BLEND));
1709 fHWBlendDisabled = false;
1710 }
1711 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1712 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1713 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1714 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1715 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1716 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1717 }
1718 } else {
1719 bool blendOff = canDisableBlend();
1720 if (fHWBlendDisabled != blendOff) {
1721 if (blendOff) {
1722 GR_GL(Disable(GR_GL_BLEND));
1723 } else {
1724 GR_GL(Enable(GR_GL_BLEND));
1725 }
1726 fHWBlendDisabled = blendOff;
1727 }
1728 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001729 if (fHWDrawState.fSrcBlend != srcCoeff ||
1730 fHWDrawState.fDstBlend != dstCoeff) {
1731 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1732 gXfermodeCoeff2Blend[dstCoeff]));
1733 fHWDrawState.fSrcBlend = srcCoeff;
1734 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001735 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001736 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1737 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001738 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1739
1740 float c[] = {
1741 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1742 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1743 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1744 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1745 };
1746 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1747 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1748 }
1749 }
1750 }
1751}
1752
bsalomon@google.comffca4002011-02-22 20:34:01 +00001753bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001754
1755 // GrGpu::setupClipAndFlushState should have already checked this
1756 // and bailed if not true.
1757 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001758
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001759 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001760 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001761 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001762 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001763
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001764 // true for now, but maybe not with GrEffect.
1765 GrAssert(NULL != nextTexture);
1766 // if we created a rt/tex and rendered to it without using a
1767 // texture and now we're texuring from the rt it will still be
1768 // the last bound texture, but it needs resolving. So keep this
1769 // out of the "last != next" check.
1770 GrGLRenderTarget* texRT =
1771 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1772 if (NULL != texRT) {
1773 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001774 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001775
1776 if (fHWDrawState.fTextures[s] != nextTexture) {
1777 setTextureUnit(s);
1778 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1779 #if GR_COLLECT_STATS
1780 ++fStats.fTextureChngCnt;
1781 #endif
1782 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1783 fHWDrawState.fTextures[s] = nextTexture;
bsalomon@google.comcd19a5f2011-06-15 14:00:23 +00001784 // The texture matrix has to compensate for texture width/height
1785 // and NPOT-embedded-in-POT
1786 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001787 }
1788
1789 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1790 const GrGLTexture::TexParams& oldTexParams =
1791 nextTexture->getTexParams();
1792 GrGLTexture::TexParams newTexParams;
1793
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001794 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1795 newTexParams.fFilter = GR_GL_NEAREST;
1796 } else {
1797 newTexParams.fFilter = GR_GL_LINEAR;
1798 }
1799
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001800 newTexParams.fWrapS =
1801 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1802 newTexParams.fWrapT =
1803 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1804
1805 if (newTexParams.fFilter != oldTexParams.fFilter) {
1806 setTextureUnit(s);
1807 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1808 GR_GL_TEXTURE_MAG_FILTER,
1809 newTexParams.fFilter));
1810 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1811 GR_GL_TEXTURE_MIN_FILTER,
1812 newTexParams.fFilter));
1813 }
1814 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1815 setTextureUnit(s);
1816 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1817 GR_GL_TEXTURE_WRAP_S,
1818 newTexParams.fWrapS));
1819 }
1820 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1821 setTextureUnit(s);
1822 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1823 GR_GL_TEXTURE_WRAP_T,
1824 newTexParams.fWrapT));
1825 }
1826 nextTexture->setTexParams(newTexParams);
reed@google.comac10a2d2010-12-22 21:39:39 +00001827 }
1828 }
1829
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001830 GrIRect* rect = NULL;
1831 GrIRect clipBounds;
1832 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1833 fClip.hasConservativeBounds()) {
1834 fClip.getConservativeBounds().roundOut(&clipBounds);
1835 rect = &clipBounds;
1836 }
1837 this->flushRenderTarget(rect);
1838 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001839
reed@google.comac10a2d2010-12-22 21:39:39 +00001840 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1841 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1842 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001843 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001844 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001845 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001846 }
1847 }
1848
bsalomon@google.comd302f142011-03-03 13:54:13 +00001849 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1850 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001851 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001852 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001853 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001854 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001855 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001856 }
1857 GR_GL(ColorMask(mask, mask, mask, mask));
1858 }
1859
bsalomon@google.comd302f142011-03-03 13:54:13 +00001860 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1861 switch (fCurrDrawState.fDrawFace) {
1862 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001863 GR_GL(Enable(GR_GL_CULL_FACE));
1864 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001865 break;
1866 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001867 GR_GL(Enable(GR_GL_CULL_FACE));
1868 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001869 break;
1870 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001871 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001872 break;
1873 default:
1874 GrCrash("Unknown draw face.");
1875 }
1876 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1877 }
1878
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001879#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001880 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001881 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001882 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001883 NULL == fCurrDrawState.fRenderTarget ||
1884 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001885 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001886 fCurrDrawState.fRenderTarget);
1887 }
1888#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001889
reed@google.comac10a2d2010-12-22 21:39:39 +00001890 flushStencil();
1891
bsalomon@google.comd302f142011-03-03 13:54:13 +00001892 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001893 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001894 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001895}
1896
1897void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001898 if (fHWGeometryState.fVertexBuffer != buffer) {
1899 fHWGeometryState.fArrayPtrsDirty = true;
1900 fHWGeometryState.fVertexBuffer = buffer;
1901 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001902}
1903
1904void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001905 if (fHWGeometryState.fVertexBuffer == buffer) {
1906 // deleting bound buffer does implied bind to 0
1907 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001908 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001909 }
1910}
1911
1912void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1913 fGeometrySrc.fIndexBuffer = buffer;
1914}
1915
1916void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001917 if (fHWGeometryState.fIndexBuffer == buffer) {
1918 // deleting bound buffer does implied bind to 0
1919 fHWGeometryState.fIndexBuffer = NULL;
1920 }
1921}
1922
reed@google.comac10a2d2010-12-22 21:39:39 +00001923void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1924 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001925 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001926 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001927 }
1928 if (fHWDrawState.fRenderTarget == renderTarget) {
1929 fHWDrawState.fRenderTarget = NULL;
1930 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001931}
1932
1933void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001934 for (int s = 0; s < kNumStages; ++s) {
1935 if (fCurrDrawState.fTextures[s] == texture) {
1936 fCurrDrawState.fTextures[s] = NULL;
1937 }
1938 if (fHWDrawState.fTextures[s] == texture) {
1939 // deleting bound texture does implied bind to 0
1940 fHWDrawState.fTextures[s] = NULL;
1941 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001942 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001943}
1944
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001945bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001946 GrGLenum* internalFormat,
1947 GrGLenum* format,
1948 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001949 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001950 case kRGBA_8888_GrPixelConfig:
1951 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001952 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001953 if (GR_GL_SUPPORT_ES) {
1954 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1955 // format for a BGRA is BGRA not RGBA (as on desktop)
1956 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1957 } else {
1958 *internalFormat = GR_GL_RGBA;
1959 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001960 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001961 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001962 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001963 *format = GR_GL_RGB;
1964 *internalFormat = GR_GL_RGB;
1965 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001966 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001967 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001968 *format = GR_GL_RGBA;
1969 *internalFormat = GR_GL_RGBA;
1970 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001971 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001972 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001973 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001974 *format = GR_GL_PALETTE8_RGBA8;
1975 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001976 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001977 } else {
1978 return false;
1979 }
1980 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001981 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001982 *format = GR_GL_ALPHA;
1983 *internalFormat = GR_GL_ALPHA;
1984 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001985 break;
1986 default:
1987 return false;
1988 }
1989 return true;
1990}
1991
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001992void GrGpuGL::setTextureUnit(int unit) {
1993 GrAssert(unit >= 0 && unit < kNumStages);
1994 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001995 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001996 fActiveTextureUnitIdx = unit;
1997 }
1998}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001999
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002000void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002001 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2002 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002003 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
2004 }
2005}
2006
reed@google.comac10a2d2010-12-22 21:39:39 +00002007/* On ES the internalFormat and format must match for TexImage and we use
2008 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
2009 decide the internalFormat. However, on ES internalFormat for
2010 RenderBufferStorage* has to be a specific format (not a base format like
2011 GL_RGBA).
2012 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002013bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002014 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002015 case kRGBA_8888_GrPixelConfig:
2016 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002017 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002018 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00002019 return true;
2020 } else {
2021 return false;
2022 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002023 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002024 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2025 // with FBO extension desktop GL has
2026 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002027 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002028 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002029 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002030 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002031 return true;
2032 default:
2033 return false;
2034 }
2035}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002036
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002037void GrGpuGL::resetDirtyFlags() {
2038 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2039}
2040
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002041void GrGpuGL::setBuffers(bool indexed,
2042 int* extraVertexOffset,
2043 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002044
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002045 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002046
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002047 GrGLVertexBuffer* vbuf;
2048 switch (fGeometrySrc.fVertexSrc) {
2049 case kBuffer_GeometrySrcType:
2050 *extraVertexOffset = 0;
2051 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2052 break;
2053 case kArray_GeometrySrcType:
2054 case kReserved_GeometrySrcType:
2055 finalizeReservedVertices();
2056 *extraVertexOffset = fCurrPoolStartVertex;
2057 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2058 break;
2059 default:
2060 vbuf = NULL; // suppress warning
2061 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002062 }
2063
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002064 GrAssert(NULL != vbuf);
2065 GrAssert(!vbuf->isLocked());
2066 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002067 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002068 fHWGeometryState.fArrayPtrsDirty = true;
2069 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002070 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002071
2072 if (indexed) {
2073 GrAssert(NULL != extraIndexOffset);
2074
2075 GrGLIndexBuffer* ibuf;
2076 switch (fGeometrySrc.fIndexSrc) {
2077 case kBuffer_GeometrySrcType:
2078 *extraIndexOffset = 0;
2079 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2080 break;
2081 case kArray_GeometrySrcType:
2082 case kReserved_GeometrySrcType:
2083 finalizeReservedIndices();
2084 *extraIndexOffset = fCurrPoolStartIndex;
2085 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2086 break;
2087 default:
2088 ibuf = NULL; // suppress warning
2089 GrCrash("Unknown geometry src type!");
2090 }
2091
2092 GrAssert(NULL != ibuf);
2093 GrAssert(!ibuf->isLocked());
2094 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002095 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002096 fHWGeometryState.fIndexBuffer = ibuf;
2097 }
2098 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002099}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002100
2101int GrGpuGL::getMaxEdges() const {
2102 // FIXME: This is a pessimistic estimate based on how many other things
2103 // want to add uniforms. This should be centralized somewhere.
2104 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2105}