blob: 177ddb105c48b4acfc1eaa5f58b59823d4758dd6 [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.com747bf292011-06-14 18:16:52 +0000474 fNPOTRenderTargetSupport = GrGLGetGLInterface()->fNPOTRenderTargetSupport;
475 if (fNPOTRenderTargetSupport < 0) {
476 fNPOTRenderTargetSupport =
477 probe_for_npot_render_target_support(fNPOTTextureSupport);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000478 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000479
bsalomon@google.com0748f212011-02-01 22:56:16 +0000480 if (gPrintStartupSpew) {
481 if (fNPOTTextureSupport) {
482 GrPrintf("NPOT textures supported\n");
483 if (fNPOTTextureTileSupport) {
484 GrPrintf("NPOT texture tiling supported\n");
485 } else {
486 GrPrintf("NPOT texture tiling NOT supported\n");
487 }
488 if (fNPOTRenderTargetSupport) {
489 GrPrintf("NPOT render targets supported\n");
490 } else {
491 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000492 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000493 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000494 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000495 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000496 }
497
bsalomon@google.com91958362011-06-13 17:58:13 +0000498 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
499 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
tomhudson@google.com747bf292011-06-14 18:16:52 +0000500 // Our render targets are always created with textures as the color
bsalomon@google.com91958362011-06-13 17:58:13 +0000501 // attachment, hence this min:
502 fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000503
tomhudson@google.com747bf292011-06-14 18:16:52 +0000504 fMinRenderTargetHeight = GrGLGetGLInterface()->fMinRenderTargetHeight;
505 if (fMinRenderTargetHeight < 0) {
506 fMinRenderTargetHeight =
507 probe_for_min_render_target_height(fNPOTRenderTargetSupport,
508 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000509 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000510
tomhudson@google.com747bf292011-06-14 18:16:52 +0000511 fMinRenderTargetWidth = GrGLGetGLInterface()->fMinRenderTargetWidth;
512 if (fMinRenderTargetWidth < 0) {
513 fMinRenderTargetWidth =
514 probe_for_min_render_target_width(fNPOTRenderTargetSupport,
515 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000516 }
tomhudson@google.com747bf292011-06-14 18:16:52 +0000517
reed@google.comac10a2d2010-12-22 21:39:39 +0000518}
519
520GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000521}
522
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000523void GrGpuGL::resetContext() {
524 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000525 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000526 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000527
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000528 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000529 GR_GL(Disable(GR_GL_DEPTH_TEST));
530 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000531
twiz@google.com0f31ca72011-03-18 17:38:11 +0000532 GR_GL(Disable(GR_GL_CULL_FACE));
533 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000534 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000535
twiz@google.com0f31ca72011-03-18 17:38:11 +0000536 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000537 if (GR_GL_SUPPORT_DESKTOP) {
538 GR_GL(Disable(GR_GL_LINE_SMOOTH));
539 GR_GL(Disable(GR_GL_POINT_SMOOTH));
540 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000541 fHWAAState.fMSAAEnabled = false;
542 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000543 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000544
twiz@google.com0f31ca72011-03-18 17:38:11 +0000545 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000546 fHWDrawState.fFlagBits = 0;
547
reed@google.comac10a2d2010-12-22 21:39:39 +0000548 // we only ever use lines in hairline mode
549 GR_GL(LineWidth(1));
550
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000551 // invalid
552 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000553
reed@google.comac10a2d2010-12-22 21:39:39 +0000554 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000555 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
556 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000557
558 fHWDrawState.fBlendConstant = 0x00000000;
559 GR_GL(BlendColor(0,0,0,0));
560
reed@google.comac10a2d2010-12-22 21:39:39 +0000561 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000562
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000563 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000564
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000565 for (int s = 0; s < kNumStages; ++s) {
566 fHWDrawState.fTextures[s] = NULL;
567 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
568 -GR_ScalarMax,
569 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000570
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000571 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000572 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000573
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000574 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000575 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000576 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000577 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000578
bsalomon@google.comd302f142011-03-03 13:54:13 +0000579 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000580 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000581 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000582
583 fHWGeometryState.fIndexBuffer = NULL;
584 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000585
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000586 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000587
twiz@google.com0f31ca72011-03-18 17:38:11 +0000588 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000589 fHWDrawState.fRenderTarget = NULL;
590}
591
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000592GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
593
594 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
595 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
596 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
597 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
598
599 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
600 if (isRenderTarget) {
601 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
602 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
603 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
604 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
605 } else {
606 GrAssert(!isTexture); // this should have been filtered by GrContext
607 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
608 }
609 } else {
610 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
611 }
612 // we don't know what the RB ids are without glGets and we don't care
613 // since we aren't responsible for deleting them.
614 rtIDs.fStencilRenderbufferID = 0;
615 rtIDs.fMSColorRenderbufferID = 0;
616
617 rtIDs.fOwnIDs = false;
618 } else {
619 rtIDs.reset();
620 }
621
622 if (isTexture) {
623 GrGLTexture::GLTextureDesc texDesc;
624 GrGLenum dontCare;
625 if (!canBeTexture(desc.fConfig, &dontCare,
626 &texDesc.fUploadFormat,
627 &texDesc.fUploadType)) {
628 return NULL;
629 }
630
631 GrGLTexture::TexParams params;
632
633 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
634 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
635
636 texDesc.fFormat = texDesc.fFormat;
637 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
638 texDesc.fStencilBits = desc.fStencilBits;
639 texDesc.fTextureID = desc.fPlatformTexture;
640 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
641 texDesc.fOwnsID = false;
642
643 params.invalidate(); // rather than do glGets.
644
645 return new GrGLTexture(this, texDesc, rtIDs, params);
646 } else {
647 GrGLIRect viewport;
648 viewport.fLeft = 0;
649 viewport.fBottom = 0;
650 viewport.fWidth = desc.fWidth;
651 viewport.fHeight = desc.fHeight;
652
653 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
654 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
655 viewport, NULL);
656 }
657}
658
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000659GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000660
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000661 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000662
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000663 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000664 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
665 rtIDs.fMSColorRenderbufferID = 0;
666 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000667
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000668 GrGLIRect viewport;
669 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000670 GrGLuint stencilBits;
671 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000672
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000673 GrGLint samples;
674 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
675
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000676 rtIDs.fOwnIDs = false;
677
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000678 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
679 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000680}
681
bsalomon@google.com5782d712011-01-21 21:03:59 +0000682///////////////////////////////////////////////////////////////////////////////
683
twiz@google.com0f31ca72011-03-18 17:38:11 +0000684static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000685
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000686struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000687 GrGLenum fEnum;
688 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000689 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000690};
691
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000692const StencilFormat* GrGLStencilFormats() {
693 // defines stencil formats from more to less preferred
694 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000695 {GR_GL_STENCIL_INDEX8, 8, false},
696 {GR_GL_STENCIL_INDEX16, 16, false},
697 {GR_GL_DEPTH24_STENCIL8, 8, true },
698 {GR_GL_STENCIL_INDEX4, 4, false},
699 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
700 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
701 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000702 };
703
704 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000705 {GR_GL_STENCIL_INDEX8, 8, false},
706 {GR_GL_DEPTH24_STENCIL8, 8, true },
707 {GR_GL_STENCIL_INDEX4, 4, false},
708 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000709 };
710
711 if (GR_GL_SUPPORT_DESKTOP) {
712 return desktopStencilFormats;
713 } else {
714 return esStencilFormats;
715 }
716}
717
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000718// good to set a break-point here to know when createTexture fails
719static GrTexture* return_null_texture() {
720// GrAssert(!"null texture");
721 return NULL;
722}
723
724#if GR_DEBUG
725static size_t as_size_t(int x) {
726 return x;
727}
728#endif
729
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000730GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000731 const void* srcData,
732 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000733
734#if GR_COLLECT_STATS
735 ++fStats.fTextureCreateCnt;
736#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000737
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000738 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000739
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000740 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000741 GR_GL_NEAREST,
742 GR_GL_CLAMP_TO_EDGE,
743 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000744 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000745
reed@google.comac10a2d2010-12-22 21:39:39 +0000746 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000747 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000748
749 glDesc.fContentWidth = desc.fWidth;
750 glDesc.fContentHeight = desc.fHeight;
751 glDesc.fAllocWidth = desc.fWidth;
752 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000753 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000754 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000755 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000756
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000757 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000758 if (!canBeTexture(desc.fFormat,
759 &internalFormat,
760 &glDesc.fUploadFormat,
761 &glDesc.fUploadType)) {
762 return return_null_texture();
763 }
764
765 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000766 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000767 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000768 GrPrintf("AA RT requested but not supported on this platform.");
769 }
770
771 GR_GL(GenTextures(1, &glDesc.fTextureID));
772 if (!glDesc.fTextureID) {
773 return return_null_texture();
774 }
775
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000776 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000777
reed@google.com5e762232011-04-04 18:15:49 +0000778 // in case we need a temporary, trimmed copy of the src pixels
779 GrAutoSMalloc<128 * 128> trimStorage;
780
reed@google.comac10a2d2010-12-22 21:39:39 +0000781 /*
782 * check if our srcData has extra bytes past each row. If so, we need
783 * to trim those off here, since GL doesn't let us pass the rowBytes as
784 * a parameter to glTexImage2D
785 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000786 if (GR_GL_SUPPORT_DESKTOP) {
787 if (srcData) {
788 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
789 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000790 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000791 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000792 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
793 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000794 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000795 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000796 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000797 char* dst = (char*)trimStorage.realloc(trimSize);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000798 for (int y = 0; y < desc.fHeight; y++) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000799 memcpy(dst, src, trimRowBytes);
800 src += rowBytes;
801 dst += trimRowBytes;
802 }
803 // now point srcData to our trimmed version
804 srcData = trimStorage.get();
805 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000806 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000807
reed@google.comac10a2d2010-12-22 21:39:39 +0000808 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000809 if (!this->npotRenderTargetSupport()) {
810 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
811 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
812 }
813
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000814 glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
815 glDesc.fAllocWidth);
816 glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
817 glDesc.fAllocHeight);
818 if (glDesc.fAllocWidth > fMaxRenderTargetSize ||
819 glDesc.fAllocHeight > fMaxRenderTargetSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000820 return return_null_texture();
821 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000822 } else if (!this->npotTextureSupport()) {
823 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
824 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000825 if (glDesc.fAllocWidth > fMaxTextureSize ||
826 glDesc.fAllocHeight > fMaxTextureSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000827 return return_null_texture();
828 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000829 }
830
twiz@google.com0f31ca72011-03-18 17:38:11 +0000831 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
832 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
833 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000834 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000835 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
836 GR_GL_TEXTURE_MIN_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_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000840 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000841 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
842 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000843 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000844
twiz@google.com0f31ca72011-03-18 17:38:11 +0000845 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000846 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000847 supports8BitPalette()) {
848 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
849 GrAssert(desc.fWidth == glDesc.fAllocWidth);
850 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000851 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000852 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000853 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000854 glDesc.fAllocWidth, glDesc.fAllocHeight,
855 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000856 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000857 } else {
858 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
859 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000860 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000861 glDesc.fAllocWidth, glDesc.fAllocHeight,
862 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000863 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000864 desc.fHeight, glDesc.fUploadFormat,
865 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000866 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000867
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000868 int extraW = glDesc.fAllocWidth - desc.fWidth;
869 int extraH = glDesc.fAllocHeight - desc.fHeight;
870 int maxTexels = extraW * extraH;
reed@google.comac10a2d2010-12-22 21:39:39 +0000871 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
872 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
873
874 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
875
876 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
877 if (extraH) {
878 uint8_t* lastRowStart = (uint8_t*) srcData +
879 (desc.fHeight - 1) * rowSize;
880 uint8_t* extraRowStart = (uint8_t*)texels.get();
881
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000882 for (int i = 0; i < extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000883 memcpy(extraRowStart, lastRowStart, rowSize);
884 extraRowStart += rowSize;
885 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000886 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000887 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
888 texels.get()));
889 }
890 if (extraW) {
891 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
892 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000893 for (int j = 0; j < desc.fHeight; ++j) {
894 for (int i = 0; i < extraW; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000895 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
896 extraTexel += glDesc.fUploadByteCount;
897 }
898 edgeTexel += rowSize;
899 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000900 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000901 desc.fHeight, glDesc.fUploadFormat,
902 glDesc.fUploadType, texels.get()));
903 }
904 if (extraW && extraH) {
905 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
906 - glDesc.fUploadByteCount;
907 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000908 for (int i = 0; i < extraW*extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000909 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
910 extraTexel += glDesc.fUploadByteCount;
911 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000912 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000913 extraW, extraH, glDesc.fUploadFormat,
914 glDesc.fUploadType, texels.get()));
915 }
916
917 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000918 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000919 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
920 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000921 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 }
923 }
924
925 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
926
927 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
928 rtIDs.fStencilRenderbufferID = 0;
929 rtIDs.fMSColorRenderbufferID = 0;
930 rtIDs.fRTFBOID = 0;
931 rtIDs.fTexFBOID = 0;
932 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000933 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000934
935 if (renderTarget) {
936#if GR_COLLECT_STATS
937 ++fStats.fRenderTargetCreateCnt;
938#endif
939 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000940 GrGLenum status;
941 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000942
943 // If need have both RT flag and srcData we have
944 // to invert the data before uploading because FBO
945 // will be rendered bottom up
946 GrAssert(NULL == srcData);
947 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
948
twiz@google.com59a190b2011-03-14 21:23:01 +0000949 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000950 GrAssert(rtIDs.fTexFBOID);
951
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000952 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000953 // to one and then resolve to the texture bound to the other.
954 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000955 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000956 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000957 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000958 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
959 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000960 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000961 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000962 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
963 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000964 return return_null_texture();
965 }
966 } else {
967 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
968 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000969 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000970 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000971 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000972 }
973
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000974 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000975 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000976 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000977 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000978
twiz@google.com0f31ca72011-03-18 17:38:11 +0000979 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000980
981 const StencilFormat* stencilFormats = GrGLStencilFormats();
982 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000983 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000984 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000985 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000986 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000987 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000988 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000989 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000990 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000991 glDesc.fAllocWidth,
992 glDesc.fAllocHeight));
993 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000994 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000995 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000996 glDesc.fAllocWidth,
997 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000998 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000999 err = GrGLGetGLInterface()->fGetError();
1000 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001001 continue;
1002 }
1003 }
1004 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
1005 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001006 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001007 rtIDs.fMSColorRenderbufferID));
1008 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001009 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001010 samples,
1011 msColorRenderbufferFormat,
1012 glDesc.fAllocWidth,
1013 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001014 err = GrGLGetGLInterface()->fGetError();
1015 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001016 continue;
1017 }
1018 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001019 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001020
1021#if GR_COLLECT_STATS
1022 ++fStats.fRenderTargetChngCnt;
1023#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001024 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1025 GR_GL_COLOR_ATTACHMENT0,
1026 GR_GL_TEXTURE_2D,
1027 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001028 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001029 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1030 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001031 continue;
1032 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001033 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001034 #if GR_COLLECT_STATS
1035 ++fStats.fRenderTargetChngCnt;
1036 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001037 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1038 GR_GL_COLOR_ATTACHMENT0,
1039 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001040 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001041
1042 }
1043 if (rtIDs.fStencilRenderbufferID) {
1044 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001045 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1046 GR_GL_STENCIL_ATTACHMENT,
1047 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001048 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001049 // if it is a packed format bind to depth also, otherwise
1050 // we may get an unsupported fbo completeness result
1051 if (stencilFormats[i].fPacked) {
1052 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1053 GR_GL_DEPTH_ATTACHMENT,
1054 GR_GL_RENDERBUFFER,
1055 rtIDs.fStencilRenderbufferID));
1056 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001057 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001058 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001059
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001060 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001061 // undo the depth bind
1062 if (rtIDs.fStencilRenderbufferID &&
1063 stencilFormats[i].fPacked) {
1064 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1065 GR_GL_DEPTH_ATTACHMENT,
1066 GR_GL_RENDERBUFFER,
1067 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001068 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001069 continue;
1070 }
1071 // we're successful!
1072 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001073 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001074 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001075 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001076 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001077 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001078 }
1079 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001080 break;
1081 }
1082 if (failed) {
1083 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001084 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001085 }
1086 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001087 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 }
1089 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001090 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001091 }
1092 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001093 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 }
1095 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1096 return return_null_texture();
1097 }
1098 }
1099#ifdef TRACE_TEXTURE_CREATION
1100 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1101 tex->fTextureID, width, height, tex->fUploadByteCount);
1102#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001103 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001104
1105 if (0 != rtIDs.fTexFBOID) {
1106 GrRenderTarget* rt = tex->asRenderTarget();
1107 // We've messed with FBO state but may not have set the correct viewport
1108 // so just dirty the rendertarget state to force a resend.
1109 fHWDrawState.fRenderTarget = NULL;
1110
1111 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001112 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001113 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1114 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001115 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001116 fCurrDrawState.fRenderTarget = rtSave;
1117 }
1118 }
1119 return tex;
1120}
1121
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001122GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001123 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001124 GR_GL(GenBuffers(1, &id));
1125 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001126 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001127 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001128 GrGLClearErr();
1129 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001130 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1131 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1132 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001133 GR_GL(DeleteBuffers(1, &id));
1134 // deleting bound buffer does implicit bind to 0
1135 fHWGeometryState.fVertexBuffer = NULL;
1136 return NULL;
1137 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001138 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001139 size, dynamic);
1140 fHWGeometryState.fVertexBuffer = vertexBuffer;
1141 return vertexBuffer;
1142 }
1143 return NULL;
1144}
1145
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001146GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001147 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001148 GR_GL(GenBuffers(1, &id));
1149 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001150 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001151 GrGLClearErr();
1152 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001153 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1154 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1155 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 GR_GL(DeleteBuffers(1, &id));
1157 // deleting bound buffer does implicit bind to 0
1158 fHWGeometryState.fIndexBuffer = NULL;
1159 return NULL;
1160 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001161 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001162 size, dynamic);
1163 fHWGeometryState.fIndexBuffer = indexBuffer;
1164 return indexBuffer;
1165 }
1166 return NULL;
1167}
1168
reed@google.comac10a2d2010-12-22 21:39:39 +00001169void GrGpuGL::flushScissor(const GrIRect* rect) {
1170 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001171 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001172 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001173
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001174 GrGLIRect scissor;
1175 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001176 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001177 rect->width(), rect->height());
1178 if (scissor.contains(vp)) {
1179 rect = NULL;
1180 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001181 }
1182
1183 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001184 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001185 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001186 fHWBounds.fScissorRect = scissor;
1187 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001188 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001189 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001190 fHWBounds.fScissorEnabled = true;
1191 }
1192 } else {
1193 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001194 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001195 fHWBounds.fScissorEnabled = false;
1196 }
1197 }
1198}
1199
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001200void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001201 if (NULL == fCurrDrawState.fRenderTarget) {
1202 return;
1203 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001204 GrIRect r;
1205 if (NULL != rect) {
1206 // flushScissor expects rect to be clipped to the target.
1207 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001208 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1209 fCurrDrawState.fRenderTarget->height());
1210 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001211 rect = &r;
1212 } else {
1213 return;
1214 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001215 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001216 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001217 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001218 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001219 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001220 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1221 GrColorUnpackG(color)/255.f,
1222 GrColorUnpackB(color)/255.f,
1223 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001224 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001225}
1226
bsalomon@google.com398109c2011-04-14 18:40:27 +00001227void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001228 if (NULL == fCurrDrawState.fRenderTarget) {
1229 return;
1230 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001231
1232 this->flushRenderTarget(&GrIRect::EmptyIRect());
1233
reed@google.comac10a2d2010-12-22 21:39:39 +00001234 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001235 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001236 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001237 }
1238 GR_GL(StencilMask(mask));
1239 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001240 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001241 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001242}
1243
bsalomon@google.com398109c2011-04-14 18:40:27 +00001244void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001245 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001246#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001247 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001248 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001249 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001250#else
1251 // we could just clear the clip bit but when we go through
1252 // angle a partial stencil mask will cause clears to be
1253 // turned into draws. Our contract on GrDrawTarget says that
1254 // changing the clip between stencil passes may or may not
1255 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001256 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001257#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001258 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001259 flushScissor(&rect);
1260 GR_GL(StencilMask(clipStencilMask));
1261 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001262 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001263 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001264}
1265
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001266void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001267 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001268}
1269
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001270bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1271 int left, int top, int width, int height,
1272 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001273 GrGLenum internalFormat; // we don't use this for glReadPixels
1274 GrGLenum format;
1275 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001276 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1277 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001278 }
1279 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1280 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1281 switch (tgt->getResolveType()) {
1282 case GrGLRenderTarget::kCantResolve_ResolveType:
1283 return false;
1284 case GrGLRenderTarget::kAutoResolves_ResolveType:
1285 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1286 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001287 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001288 break;
1289 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001290 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001291 // we don't track the state of the READ FBO ID.
1292 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1293 break;
1294 default:
1295 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001296 }
1297
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001298 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001299
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001300 // the read rect is viewport-relative
1301 GrGLIRect readRect;
1302 readRect.setRelativeTo(glvp, left, top, width, height);
1303 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001304 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001305 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001306
1307 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1308 // API presents top-to-bottom
1309 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001310 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001311 GrAutoMalloc rowStorage(stride);
1312 void* tmp = rowStorage.get();
1313
1314 const int halfY = height >> 1;
1315 char* top = reinterpret_cast<char*>(buffer);
1316 char* bottom = top + (height - 1) * stride;
1317 for (int y = 0; y < halfY; y++) {
1318 memcpy(tmp, top, stride);
1319 memcpy(top, bottom, stride);
1320 memcpy(bottom, tmp, stride);
1321 top += stride;
1322 bottom -= stride;
1323 }
1324 }
1325 return true;
1326}
1327
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001328void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001329
1330 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1331
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001332 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001333 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001334 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001335 #if GR_COLLECT_STATS
1336 ++fStats.fRenderTargetChngCnt;
1337 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001338 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001339 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1340 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001341 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001342 }
1343 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001344 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001345 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001346 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001347 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001348 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001349 fHWBounds.fViewportRect = vp;
1350 }
1351 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001352 if (NULL == bound || !bound->isEmpty()) {
1353 rt->flagAsNeedingResolve(bound);
1354 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001355}
1356
twiz@google.com0f31ca72011-03-18 17:38:11 +00001357GrGLenum gPrimitiveType2GLMode[] = {
1358 GR_GL_TRIANGLES,
1359 GR_GL_TRIANGLE_STRIP,
1360 GR_GL_TRIANGLE_FAN,
1361 GR_GL_POINTS,
1362 GR_GL_LINES,
1363 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001364};
1365
bsalomon@google.comd302f142011-03-03 13:54:13 +00001366#define SWAP_PER_DRAW 0
1367
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001368#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001369 #if GR_MAC_BUILD
1370 #include <AGL/agl.h>
1371 #elif GR_WIN32_BUILD
1372 void SwapBuf() {
1373 DWORD procID = GetCurrentProcessId();
1374 HWND hwnd = GetTopWindow(GetDesktopWindow());
1375 while(hwnd) {
1376 DWORD wndProcID = 0;
1377 GetWindowThreadProcessId(hwnd, &wndProcID);
1378 if(wndProcID == procID) {
1379 SwapBuffers(GetDC(hwnd));
1380 }
1381 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1382 }
1383 }
1384 #endif
1385#endif
1386
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001387void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1388 uint32_t startVertex,
1389 uint32_t startIndex,
1390 uint32_t vertexCount,
1391 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001392 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1393
twiz@google.com0f31ca72011-03-18 17:38:11 +00001394 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001395
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001396 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1397 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1398
1399 // our setupGeometry better have adjusted this to zero since
1400 // DrawElements always draws from the begining of the arrays for idx 0.
1401 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001402
1403 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001404 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001405#if SWAP_PER_DRAW
1406 glFlush();
1407 #if GR_MAC_BUILD
1408 aglSwapBuffers(aglGetCurrentContext());
1409 int set_a_break_pt_here = 9;
1410 aglSwapBuffers(aglGetCurrentContext());
1411 #elif GR_WIN32_BUILD
1412 SwapBuf();
1413 int set_a_break_pt_here = 9;
1414 SwapBuf();
1415 #endif
1416#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001417}
1418
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001419void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1420 uint32_t startVertex,
1421 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001422 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1423
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001424 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1425
1426 // our setupGeometry better have adjusted this to zero.
1427 // DrawElements doesn't take an offset so we always adjus the startVertex.
1428 GrAssert(0 == startVertex);
1429
1430 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1431 // account for startVertex in the DrawElements case. So we always
1432 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001433 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001434#if SWAP_PER_DRAW
1435 glFlush();
1436 #if GR_MAC_BUILD
1437 aglSwapBuffers(aglGetCurrentContext());
1438 int set_a_break_pt_here = 9;
1439 aglSwapBuffers(aglGetCurrentContext());
1440 #elif GR_WIN32_BUILD
1441 SwapBuf();
1442 int set_a_break_pt_here = 9;
1443 SwapBuf();
1444 #endif
1445#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001446}
1447
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001448void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001449
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001450 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001451 GrAssert(kNone_MSFBO != fMSFBOType);
1452 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001453 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001454 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001455 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001456 rt->textureFBOID()));
1457 #if GR_COLLECT_STATS
1458 ++fStats.fRenderTargetChngCnt;
1459 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001460 // make sure we go through flushRenderTarget() since we've modified
1461 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001462 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001463 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001464 const GrIRect dirtyRect = rt->getResolveRect();
1465 GrGLIRect r;
1466 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1467 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001468
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001469 if (kAppleES_MSFBO == fMSFBOType) {
1470 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001471 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001472 GR_GL(Scissor(r.fLeft, r.fBottom,
1473 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001474 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001475 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001476 fHWBounds.fScissorEnabled = true;
1477 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001478 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001479 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001480 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1481 flushScissor(NULL);
1482 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001483 int right = r.fLeft + r.fWidth;
1484 int top = r.fBottom + r.fHeight;
1485 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1486 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001487 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001488 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001489 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001490 }
1491}
1492
twiz@google.com0f31ca72011-03-18 17:38:11 +00001493static const GrGLenum grToGLStencilFunc[] = {
1494 GR_GL_ALWAYS, // kAlways_StencilFunc
1495 GR_GL_NEVER, // kNever_StencilFunc
1496 GR_GL_GREATER, // kGreater_StencilFunc
1497 GR_GL_GEQUAL, // kGEqual_StencilFunc
1498 GR_GL_LESS, // kLess_StencilFunc
1499 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1500 GR_GL_EQUAL, // kEqual_StencilFunc,
1501 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001502};
1503GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1504GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1505GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1506GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1507GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1508GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1509GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1510GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1511GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1512
twiz@google.com0f31ca72011-03-18 17:38:11 +00001513static const GrGLenum grToGLStencilOp[] = {
1514 GR_GL_KEEP, // kKeep_StencilOp
1515 GR_GL_REPLACE, // kReplace_StencilOp
1516 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1517 GR_GL_INCR, // kIncClamp_StencilOp
1518 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1519 GR_GL_DECR, // kDecClamp_StencilOp
1520 GR_GL_ZERO, // kZero_StencilOp
1521 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001522};
1523GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1524GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1525GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1526GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1527GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1528GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1529GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1530GR_STATIC_ASSERT(6 == kZero_StencilOp);
1531GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1532
reed@google.comac10a2d2010-12-22 21:39:39 +00001533void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001534 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001535
1536 // use stencil for clipping if clipping is enabled and the clip
1537 // has been written into the stencil.
1538 bool stencilClip = fClipState.fClipInStencil &&
1539 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001540 bool stencilChange = fHWStencilClip != stencilClip ||
1541 fHWDrawState.fStencilSettings != *settings ||
1542 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1543 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001544
1545 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001546
bsalomon@google.comd302f142011-03-03 13:54:13 +00001547 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1548 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001549
bsalomon@google.comd302f142011-03-03 13:54:13 +00001550 if (settings->isDisabled()) {
1551 if (stencilClip) {
1552 settings = &gClipStencilSettings;
1553 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001554 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001555
1556 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001557 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001558 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001559 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001560 #if GR_DEBUG
1561 if (!fStencilWrapOpsSupport) {
1562 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1563 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1564 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1565 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1566 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1567 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1568 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1569 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1570 }
1571 #endif
1572 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1573 GrAssert(stencilBits ||
1574 (GrStencilSettings::gDisabled ==
1575 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001576 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1577 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001578
1579 unsigned int frontRef = settings->fFrontFuncRef;
1580 unsigned int frontMask = settings->fFrontFuncMask;
1581 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001582 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001583
1584 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1585
1586 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1587 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1588 } else {
1589 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1590
1591 ConvertStencilFuncAndMask(settings->fFrontFunc,
1592 stencilClip,
1593 clipStencilMask,
1594 userStencilMask,
1595 &frontRef,
1596 &frontMask);
1597 frontWriteMask &= userStencilMask;
1598 }
1599 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001600 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001601 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001602 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001603 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001604 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001605 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001606 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001607 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001608 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001609
1610 unsigned int backRef = settings->fBackFuncRef;
1611 unsigned int backMask = settings->fBackFuncMask;
1612 unsigned int backWriteMask = settings->fBackWriteMask;
1613
1614
1615 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1616 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1617 backFunc = grToGLStencilFunc[settings->fBackFunc];
1618 } else {
1619 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1620 ConvertStencilFuncAndMask(settings->fBackFunc,
1621 stencilClip,
1622 clipStencilMask,
1623 userStencilMask,
1624 &backRef,
1625 &backMask);
1626 backWriteMask &= userStencilMask;
1627 }
1628
twiz@google.com0f31ca72011-03-18 17:38:11 +00001629 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1630 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1631 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1632 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1633 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001634 grToGLStencilOp[settings->fFrontPassOp],
1635 grToGLStencilOp[settings->fFrontPassOp]));
1636
twiz@google.com0f31ca72011-03-18 17:38:11 +00001637 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001638 grToGLStencilOp[settings->fBackPassOp],
1639 grToGLStencilOp[settings->fBackPassOp]));
1640 } else {
1641 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1642 GR_GL(StencilMask(frontWriteMask));
1643 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1644 grToGLStencilOp[settings->fFrontPassOp],
1645 grToGLStencilOp[settings->fFrontPassOp]));
1646 }
1647 }
1648 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001649 fHWStencilClip = stencilClip;
1650 }
1651}
1652
bsalomon@google.com0650e812011-04-08 18:07:53 +00001653bool GrGpuGL::useSmoothLines() {
1654 // there is a conflict between using smooth lines and our use of
1655 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1656 // but not in a premul-alpha way. So we only use them when our alpha
1657 // is 0xff.
1658
1659 // TODO: write a smarter line frag shader.
1660
1661 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1662 canDisableBlend();
1663}
1664
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001665void GrGpuGL::flushAAState(GrPrimitiveType type) {
1666 if (GR_GL_SUPPORT_DESKTOP) {
1667 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1668 // smooth lines.
1669
1670 // we prefer smooth lines over multisampled lines
1671 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001672 if (GrIsPrimTypeLines(type)) {
1673 bool smooth = useSmoothLines();
1674 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001675 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1676 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001677 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001678 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1679 fHWAAState.fSmoothLineEnabled = false;
1680 }
1681 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1682 fHWAAState.fMSAAEnabled) {
1683 GR_GL(Disable(GR_GL_MULTISAMPLE));
1684 fHWAAState.fMSAAEnabled = false;
1685 }
1686 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1687 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1688 fHWAAState.fMSAAEnabled) {
1689 if (fHWAAState.fMSAAEnabled) {
1690 GR_GL(Disable(GR_GL_MULTISAMPLE));
1691 fHWAAState.fMSAAEnabled = false;
1692 } else {
1693 GR_GL(Enable(GR_GL_MULTISAMPLE));
1694 fHWAAState.fMSAAEnabled = true;
1695 }
1696 }
1697 }
1698}
1699
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001700void GrGpuGL::flushBlend(GrPrimitiveType type,
1701 GrBlendCoeff srcCoeff,
1702 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001703 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1704 if (fHWBlendDisabled) {
1705 GR_GL(Enable(GR_GL_BLEND));
1706 fHWBlendDisabled = false;
1707 }
1708 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1709 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1710 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1711 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1712 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1713 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1714 }
1715 } else {
1716 bool blendOff = canDisableBlend();
1717 if (fHWBlendDisabled != blendOff) {
1718 if (blendOff) {
1719 GR_GL(Disable(GR_GL_BLEND));
1720 } else {
1721 GR_GL(Enable(GR_GL_BLEND));
1722 }
1723 fHWBlendDisabled = blendOff;
1724 }
1725 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001726 if (fHWDrawState.fSrcBlend != srcCoeff ||
1727 fHWDrawState.fDstBlend != dstCoeff) {
1728 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1729 gXfermodeCoeff2Blend[dstCoeff]));
1730 fHWDrawState.fSrcBlend = srcCoeff;
1731 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001732 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001733 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1734 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001735 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1736
1737 float c[] = {
1738 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1739 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1740 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1741 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1742 };
1743 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1744 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1745 }
1746 }
1747 }
1748}
1749
bsalomon@google.comffca4002011-02-22 20:34:01 +00001750bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001751
1752 // GrGpu::setupClipAndFlushState should have already checked this
1753 // and bailed if not true.
1754 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001755
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001756 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001757 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001758 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001759 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001760
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001761 // true for now, but maybe not with GrEffect.
1762 GrAssert(NULL != nextTexture);
1763 // if we created a rt/tex and rendered to it without using a
1764 // texture and now we're texuring from the rt it will still be
1765 // the last bound texture, but it needs resolving. So keep this
1766 // out of the "last != next" check.
1767 GrGLRenderTarget* texRT =
1768 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1769 if (NULL != texRT) {
1770 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001771 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001772
1773 if (fHWDrawState.fTextures[s] != nextTexture) {
1774 setTextureUnit(s);
1775 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1776 #if GR_COLLECT_STATS
1777 ++fStats.fTextureChngCnt;
1778 #endif
1779 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1780 fHWDrawState.fTextures[s] = nextTexture;
bsalomon@google.comcd19a5f2011-06-15 14:00:23 +00001781 // The texture matrix has to compensate for texture width/height
1782 // and NPOT-embedded-in-POT
1783 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001784 }
1785
1786 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1787 const GrGLTexture::TexParams& oldTexParams =
1788 nextTexture->getTexParams();
1789 GrGLTexture::TexParams newTexParams;
1790
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001791 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1792 newTexParams.fFilter = GR_GL_NEAREST;
1793 } else {
1794 newTexParams.fFilter = GR_GL_LINEAR;
1795 }
1796
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001797 newTexParams.fWrapS =
1798 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1799 newTexParams.fWrapT =
1800 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1801
1802 if (newTexParams.fFilter != oldTexParams.fFilter) {
1803 setTextureUnit(s);
1804 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1805 GR_GL_TEXTURE_MAG_FILTER,
1806 newTexParams.fFilter));
1807 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1808 GR_GL_TEXTURE_MIN_FILTER,
1809 newTexParams.fFilter));
1810 }
1811 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1812 setTextureUnit(s);
1813 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1814 GR_GL_TEXTURE_WRAP_S,
1815 newTexParams.fWrapS));
1816 }
1817 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1818 setTextureUnit(s);
1819 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1820 GR_GL_TEXTURE_WRAP_T,
1821 newTexParams.fWrapT));
1822 }
1823 nextTexture->setTexParams(newTexParams);
reed@google.comac10a2d2010-12-22 21:39:39 +00001824 }
1825 }
1826
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001827 GrIRect* rect = NULL;
1828 GrIRect clipBounds;
1829 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1830 fClip.hasConservativeBounds()) {
1831 fClip.getConservativeBounds().roundOut(&clipBounds);
1832 rect = &clipBounds;
1833 }
1834 this->flushRenderTarget(rect);
1835 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001836
reed@google.comac10a2d2010-12-22 21:39:39 +00001837 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1838 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1839 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001840 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001841 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001842 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001843 }
1844 }
1845
bsalomon@google.comd302f142011-03-03 13:54:13 +00001846 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1847 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001848 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001849 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001850 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001851 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001852 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001853 }
1854 GR_GL(ColorMask(mask, mask, mask, mask));
1855 }
1856
bsalomon@google.comd302f142011-03-03 13:54:13 +00001857 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1858 switch (fCurrDrawState.fDrawFace) {
1859 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001860 GR_GL(Enable(GR_GL_CULL_FACE));
1861 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001862 break;
1863 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001864 GR_GL(Enable(GR_GL_CULL_FACE));
1865 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001866 break;
1867 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001868 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001869 break;
1870 default:
1871 GrCrash("Unknown draw face.");
1872 }
1873 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1874 }
1875
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001876#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001877 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001878 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001879 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001880 NULL == fCurrDrawState.fRenderTarget ||
1881 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001882 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001883 fCurrDrawState.fRenderTarget);
1884 }
1885#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001886
reed@google.comac10a2d2010-12-22 21:39:39 +00001887 flushStencil();
1888
bsalomon@google.comd302f142011-03-03 13:54:13 +00001889 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001890 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001891 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001892}
1893
1894void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001895 if (fHWGeometryState.fVertexBuffer != buffer) {
1896 fHWGeometryState.fArrayPtrsDirty = true;
1897 fHWGeometryState.fVertexBuffer = buffer;
1898 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001899}
1900
1901void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001902 if (fHWGeometryState.fVertexBuffer == buffer) {
1903 // deleting bound buffer does implied bind to 0
1904 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001905 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001906 }
1907}
1908
1909void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1910 fGeometrySrc.fIndexBuffer = buffer;
1911}
1912
1913void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001914 if (fHWGeometryState.fIndexBuffer == buffer) {
1915 // deleting bound buffer does implied bind to 0
1916 fHWGeometryState.fIndexBuffer = NULL;
1917 }
1918}
1919
reed@google.comac10a2d2010-12-22 21:39:39 +00001920void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1921 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001922 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001923 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001924 }
1925 if (fHWDrawState.fRenderTarget == renderTarget) {
1926 fHWDrawState.fRenderTarget = NULL;
1927 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001928}
1929
1930void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001931 for (int s = 0; s < kNumStages; ++s) {
1932 if (fCurrDrawState.fTextures[s] == texture) {
1933 fCurrDrawState.fTextures[s] = NULL;
1934 }
1935 if (fHWDrawState.fTextures[s] == texture) {
1936 // deleting bound texture does implied bind to 0
1937 fHWDrawState.fTextures[s] = NULL;
1938 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001939 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001940}
1941
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001942bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001943 GrGLenum* internalFormat,
1944 GrGLenum* format,
1945 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001946 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001947 case kRGBA_8888_GrPixelConfig:
1948 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001949 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001950 if (GR_GL_SUPPORT_ES) {
1951 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1952 // format for a BGRA is BGRA not RGBA (as on desktop)
1953 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1954 } else {
1955 *internalFormat = GR_GL_RGBA;
1956 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001957 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001958 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001959 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001960 *format = GR_GL_RGB;
1961 *internalFormat = GR_GL_RGB;
1962 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001963 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001964 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001965 *format = GR_GL_RGBA;
1966 *internalFormat = GR_GL_RGBA;
1967 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001968 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001969 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001970 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001971 *format = GR_GL_PALETTE8_RGBA8;
1972 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001973 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001974 } else {
1975 return false;
1976 }
1977 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001978 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001979 *format = GR_GL_ALPHA;
1980 *internalFormat = GR_GL_ALPHA;
1981 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001982 break;
1983 default:
1984 return false;
1985 }
1986 return true;
1987}
1988
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001989void GrGpuGL::setTextureUnit(int unit) {
1990 GrAssert(unit >= 0 && unit < kNumStages);
1991 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001992 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001993 fActiveTextureUnitIdx = unit;
1994 }
1995}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001996
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001997void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001998 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1999 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002000 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
2001 }
2002}
2003
reed@google.comac10a2d2010-12-22 21:39:39 +00002004/* On ES the internalFormat and format must match for TexImage and we use
2005 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
2006 decide the internalFormat. However, on ES internalFormat for
2007 RenderBufferStorage* has to be a specific format (not a base format like
2008 GL_RGBA).
2009 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002010bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002011 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002012 case kRGBA_8888_GrPixelConfig:
2013 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002014 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002015 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00002016 return true;
2017 } else {
2018 return false;
2019 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002020 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002021 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2022 // with FBO extension desktop GL has
2023 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002024 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002025 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002026 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002027 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002028 return true;
2029 default:
2030 return false;
2031 }
2032}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002033
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002034void GrGpuGL::resetDirtyFlags() {
2035 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2036}
2037
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002038void GrGpuGL::setBuffers(bool indexed,
2039 int* extraVertexOffset,
2040 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002041
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002042 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002043
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002044 GrGLVertexBuffer* vbuf;
2045 switch (fGeometrySrc.fVertexSrc) {
2046 case kBuffer_GeometrySrcType:
2047 *extraVertexOffset = 0;
2048 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2049 break;
2050 case kArray_GeometrySrcType:
2051 case kReserved_GeometrySrcType:
2052 finalizeReservedVertices();
2053 *extraVertexOffset = fCurrPoolStartVertex;
2054 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2055 break;
2056 default:
2057 vbuf = NULL; // suppress warning
2058 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002059 }
2060
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002061 GrAssert(NULL != vbuf);
2062 GrAssert(!vbuf->isLocked());
2063 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002064 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002065 fHWGeometryState.fArrayPtrsDirty = true;
2066 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002067 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002068
2069 if (indexed) {
2070 GrAssert(NULL != extraIndexOffset);
2071
2072 GrGLIndexBuffer* ibuf;
2073 switch (fGeometrySrc.fIndexSrc) {
2074 case kBuffer_GeometrySrcType:
2075 *extraIndexOffset = 0;
2076 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2077 break;
2078 case kArray_GeometrySrcType:
2079 case kReserved_GeometrySrcType:
2080 finalizeReservedIndices();
2081 *extraIndexOffset = fCurrPoolStartIndex;
2082 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2083 break;
2084 default:
2085 ibuf = NULL; // suppress warning
2086 GrCrash("Unknown geometry src type!");
2087 }
2088
2089 GrAssert(NULL != ibuf);
2090 GrAssert(!ibuf->isLocked());
2091 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002092 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002093 fHWGeometryState.fIndexBuffer = ibuf;
2094 }
2095 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002096}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002097
2098int GrGpuGL::getMaxEdges() const {
2099 // FIXME: This is a pessimistic estimate based on how many other things
2100 // want to add uniforms. This should be centralized somewhere.
2101 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2102}