blob: 973e1e4a53763874d5a655753dbb4cd9b549883e [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.com30e4bb62011-06-15 19:41:46 +0000474 if (GrGLGetGLInterface()->fNPOTRenderTargetSupport < 0) {
tomhudson@google.com747bf292011-06-14 18:16:52 +0000475 fNPOTRenderTargetSupport =
476 probe_for_npot_render_target_support(fNPOTTextureSupport);
tomhudson@google.com30e4bb62011-06-15 19:41:46 +0000477 } else {
478 fNPOTRenderTargetSupport = GrGLGetGLInterface()->fNPOTRenderTargetSupport;
bsalomon@google.com0748f212011-02-01 22:56:16 +0000479 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000480
bsalomon@google.com0748f212011-02-01 22:56:16 +0000481 if (gPrintStartupSpew) {
482 if (fNPOTTextureSupport) {
483 GrPrintf("NPOT textures supported\n");
484 if (fNPOTTextureTileSupport) {
485 GrPrintf("NPOT texture tiling supported\n");
486 } else {
487 GrPrintf("NPOT texture tiling NOT supported\n");
488 }
489 if (fNPOTRenderTargetSupport) {
490 GrPrintf("NPOT render targets supported\n");
491 } else {
492 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000493 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000494 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000495 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000496 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000497 }
498
bsalomon@google.com91958362011-06-13 17:58:13 +0000499 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
500 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
tomhudson@google.com747bf292011-06-14 18:16:52 +0000501 // Our render targets are always created with textures as the color
bsalomon@google.com91958362011-06-13 17:58:13 +0000502 // attachment, hence this min:
503 fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000504
tomhudson@google.com747bf292011-06-14 18:16:52 +0000505 fMinRenderTargetHeight = GrGLGetGLInterface()->fMinRenderTargetHeight;
506 if (fMinRenderTargetHeight < 0) {
507 fMinRenderTargetHeight =
508 probe_for_min_render_target_height(fNPOTRenderTargetSupport,
509 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000510 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000511
tomhudson@google.com747bf292011-06-14 18:16:52 +0000512 fMinRenderTargetWidth = GrGLGetGLInterface()->fMinRenderTargetWidth;
513 if (fMinRenderTargetWidth < 0) {
514 fMinRenderTargetWidth =
515 probe_for_min_render_target_width(fNPOTRenderTargetSupport,
516 fMaxRenderTargetSize);
reed@google.comeeeb5a02010-12-23 15:12:59 +0000517 }
tomhudson@google.com747bf292011-06-14 18:16:52 +0000518
reed@google.comac10a2d2010-12-22 21:39:39 +0000519}
520
521GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000522}
523
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000524void GrGpuGL::resetContext() {
525 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000526 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000527 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000528
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000529 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000530 GR_GL(Disable(GR_GL_DEPTH_TEST));
531 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000532
twiz@google.com0f31ca72011-03-18 17:38:11 +0000533 GR_GL(Disable(GR_GL_CULL_FACE));
534 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000535 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000536
twiz@google.com0f31ca72011-03-18 17:38:11 +0000537 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000538 if (GR_GL_SUPPORT_DESKTOP) {
539 GR_GL(Disable(GR_GL_LINE_SMOOTH));
540 GR_GL(Disable(GR_GL_POINT_SMOOTH));
541 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000542 fHWAAState.fMSAAEnabled = false;
543 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000544 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000545
twiz@google.com0f31ca72011-03-18 17:38:11 +0000546 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000547 fHWDrawState.fFlagBits = 0;
548
reed@google.comac10a2d2010-12-22 21:39:39 +0000549 // we only ever use lines in hairline mode
550 GR_GL(LineWidth(1));
551
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000552 // invalid
553 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000554
reed@google.comac10a2d2010-12-22 21:39:39 +0000555 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000556 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
557 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000558
559 fHWDrawState.fBlendConstant = 0x00000000;
560 GR_GL(BlendColor(0,0,0,0));
561
reed@google.comac10a2d2010-12-22 21:39:39 +0000562 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000563
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000564 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000565
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000566 for (int s = 0; s < kNumStages; ++s) {
567 fHWDrawState.fTextures[s] = NULL;
568 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
569 -GR_ScalarMax,
570 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000571
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000572 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000573 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000574
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000575 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000576 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000577 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000578 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000579
bsalomon@google.comd302f142011-03-03 13:54:13 +0000580 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000581 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000582 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000583
584 fHWGeometryState.fIndexBuffer = NULL;
585 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000586
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000587 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000588
twiz@google.com0f31ca72011-03-18 17:38:11 +0000589 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000590 fHWDrawState.fRenderTarget = NULL;
591}
592
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000593GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
594
595 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
596 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
597 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
598 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
599
600 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
601 if (isRenderTarget) {
602 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
603 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
604 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
605 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
606 } else {
607 GrAssert(!isTexture); // this should have been filtered by GrContext
608 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
609 }
610 } else {
611 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
612 }
613 // we don't know what the RB ids are without glGets and we don't care
614 // since we aren't responsible for deleting them.
615 rtIDs.fStencilRenderbufferID = 0;
616 rtIDs.fMSColorRenderbufferID = 0;
617
618 rtIDs.fOwnIDs = false;
619 } else {
620 rtIDs.reset();
621 }
622
623 if (isTexture) {
624 GrGLTexture::GLTextureDesc texDesc;
625 GrGLenum dontCare;
626 if (!canBeTexture(desc.fConfig, &dontCare,
627 &texDesc.fUploadFormat,
628 &texDesc.fUploadType)) {
629 return NULL;
630 }
631
632 GrGLTexture::TexParams params;
633
634 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
635 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
636
637 texDesc.fFormat = texDesc.fFormat;
638 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
639 texDesc.fStencilBits = desc.fStencilBits;
640 texDesc.fTextureID = desc.fPlatformTexture;
641 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
642 texDesc.fOwnsID = false;
643
644 params.invalidate(); // rather than do glGets.
645
646 return new GrGLTexture(this, texDesc, rtIDs, params);
647 } else {
648 GrGLIRect viewport;
649 viewport.fLeft = 0;
650 viewport.fBottom = 0;
651 viewport.fWidth = desc.fWidth;
652 viewport.fHeight = desc.fHeight;
653
654 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
655 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
656 viewport, NULL);
657 }
658}
659
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000660GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000661
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000662 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000663
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000664 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000665 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
666 rtIDs.fMSColorRenderbufferID = 0;
667 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000668
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000669 GrGLIRect viewport;
670 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000671 GrGLuint stencilBits;
672 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000673
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000674 GrGLint samples;
675 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
676
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000677 rtIDs.fOwnIDs = false;
678
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000679 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
680 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000681}
682
bsalomon@google.com5782d712011-01-21 21:03:59 +0000683///////////////////////////////////////////////////////////////////////////////
684
twiz@google.com0f31ca72011-03-18 17:38:11 +0000685static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000686
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000687struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000688 GrGLenum fEnum;
689 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000690 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000691};
692
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000693const StencilFormat* GrGLStencilFormats() {
694 // defines stencil formats from more to less preferred
695 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000696 {GR_GL_STENCIL_INDEX8, 8, false},
697 {GR_GL_STENCIL_INDEX16, 16, false},
698 {GR_GL_DEPTH24_STENCIL8, 8, true },
699 {GR_GL_STENCIL_INDEX4, 4, false},
700 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
701 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
702 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000703 };
704
705 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000706 {GR_GL_STENCIL_INDEX8, 8, false},
707 {GR_GL_DEPTH24_STENCIL8, 8, true },
708 {GR_GL_STENCIL_INDEX4, 4, false},
709 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000710 };
711
712 if (GR_GL_SUPPORT_DESKTOP) {
713 return desktopStencilFormats;
714 } else {
715 return esStencilFormats;
716 }
717}
718
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000719// good to set a break-point here to know when createTexture fails
720static GrTexture* return_null_texture() {
721// GrAssert(!"null texture");
722 return NULL;
723}
724
725#if GR_DEBUG
726static size_t as_size_t(int x) {
727 return x;
728}
729#endif
730
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000731GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000732 const void* srcData,
733 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000734
735#if GR_COLLECT_STATS
736 ++fStats.fTextureCreateCnt;
737#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000738
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000739 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000740
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000741 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000742 GR_GL_NEAREST,
743 GR_GL_CLAMP_TO_EDGE,
744 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000745 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000746
reed@google.comac10a2d2010-12-22 21:39:39 +0000747 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000748 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000749
750 glDesc.fContentWidth = desc.fWidth;
751 glDesc.fContentHeight = desc.fHeight;
752 glDesc.fAllocWidth = desc.fWidth;
753 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000754 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000755 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000756 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000757
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000758 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000759 if (!canBeTexture(desc.fFormat,
760 &internalFormat,
761 &glDesc.fUploadFormat,
762 &glDesc.fUploadType)) {
763 return return_null_texture();
764 }
765
766 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000767 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000768 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000769 GrPrintf("AA RT requested but not supported on this platform.");
770 }
771
772 GR_GL(GenTextures(1, &glDesc.fTextureID));
773 if (!glDesc.fTextureID) {
774 return return_null_texture();
775 }
776
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000777 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000778
reed@google.com5e762232011-04-04 18:15:49 +0000779 // in case we need a temporary, trimmed copy of the src pixels
780 GrAutoSMalloc<128 * 128> trimStorage;
781
reed@google.comac10a2d2010-12-22 21:39:39 +0000782 /*
783 * check if our srcData has extra bytes past each row. If so, we need
784 * to trim those off here, since GL doesn't let us pass the rowBytes as
785 * a parameter to glTexImage2D
786 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000787 if (GR_GL_SUPPORT_DESKTOP) {
788 if (srcData) {
789 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
790 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000791 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000792 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000793 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
794 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000795 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000796 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000797 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000798 char* dst = (char*)trimStorage.realloc(trimSize);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000799 for (int y = 0; y < desc.fHeight; y++) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000800 memcpy(dst, src, trimRowBytes);
801 src += rowBytes;
802 dst += trimRowBytes;
803 }
804 // now point srcData to our trimmed version
805 srcData = trimStorage.get();
806 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000807 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000808
reed@google.comac10a2d2010-12-22 21:39:39 +0000809 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000810 if (!this->npotRenderTargetSupport()) {
811 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
812 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
813 }
814
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000815 glDesc.fAllocWidth = GrMax(fMinRenderTargetWidth,
816 glDesc.fAllocWidth);
817 glDesc.fAllocHeight = GrMax(fMinRenderTargetHeight,
818 glDesc.fAllocHeight);
819 if (glDesc.fAllocWidth > fMaxRenderTargetSize ||
820 glDesc.fAllocHeight > fMaxRenderTargetSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000821 return return_null_texture();
822 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000823 } else if (!this->npotTextureSupport()) {
824 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
825 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000826 if (glDesc.fAllocWidth > fMaxTextureSize ||
827 glDesc.fAllocHeight > fMaxTextureSize) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000828 return return_null_texture();
829 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000830 }
831
twiz@google.com0f31ca72011-03-18 17:38:11 +0000832 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
833 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
834 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000835 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000836 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
837 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000838 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000839 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
840 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000841 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000842 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
843 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000844 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000845
twiz@google.com0f31ca72011-03-18 17:38:11 +0000846 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000847 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000848 supports8BitPalette()) {
849 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
850 GrAssert(desc.fWidth == glDesc.fAllocWidth);
851 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000852 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000853 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000854 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000855 glDesc.fAllocWidth, glDesc.fAllocHeight,
856 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000857 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000858 } else {
859 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
860 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000861 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000862 glDesc.fAllocWidth, glDesc.fAllocHeight,
863 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000864 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000865 desc.fHeight, glDesc.fUploadFormat,
866 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000867 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000868
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000869 int extraW = glDesc.fAllocWidth - desc.fWidth;
870 int extraH = glDesc.fAllocHeight - desc.fHeight;
871 int maxTexels = extraW * extraH;
reed@google.comac10a2d2010-12-22 21:39:39 +0000872 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
873 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
874
875 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
876
877 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
878 if (extraH) {
879 uint8_t* lastRowStart = (uint8_t*) srcData +
880 (desc.fHeight - 1) * rowSize;
881 uint8_t* extraRowStart = (uint8_t*)texels.get();
882
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000883 for (int i = 0; i < extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000884 memcpy(extraRowStart, lastRowStart, rowSize);
885 extraRowStart += rowSize;
886 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000887 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000888 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
889 texels.get()));
890 }
891 if (extraW) {
892 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
893 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000894 for (int j = 0; j < desc.fHeight; ++j) {
895 for (int i = 0; i < extraW; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000896 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
897 extraTexel += glDesc.fUploadByteCount;
898 }
899 edgeTexel += rowSize;
900 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000901 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000902 desc.fHeight, glDesc.fUploadFormat,
903 glDesc.fUploadType, texels.get()));
904 }
905 if (extraW && extraH) {
906 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
907 - glDesc.fUploadByteCount;
908 uint8_t* extraTexel = (uint8_t*)texels.get();
bsalomon@google.com79d2dbe2011-06-13 19:28:02 +0000909 for (int i = 0; i < extraW*extraH; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000910 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
911 extraTexel += glDesc.fUploadByteCount;
912 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000913 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000914 extraW, extraH, glDesc.fUploadFormat,
915 glDesc.fUploadType, texels.get()));
916 }
917
918 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000919 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000920 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
921 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000922 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000923 }
924 }
925
926 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
927
928 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
929 rtIDs.fStencilRenderbufferID = 0;
930 rtIDs.fMSColorRenderbufferID = 0;
931 rtIDs.fRTFBOID = 0;
932 rtIDs.fTexFBOID = 0;
933 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000934 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000935
936 if (renderTarget) {
937#if GR_COLLECT_STATS
938 ++fStats.fRenderTargetCreateCnt;
939#endif
940 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000941 GrGLenum status;
942 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000943
944 // If need have both RT flag and srcData we have
945 // to invert the data before uploading because FBO
946 // will be rendered bottom up
947 GrAssert(NULL == srcData);
948 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
949
twiz@google.com59a190b2011-03-14 21:23:01 +0000950 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000951 GrAssert(rtIDs.fTexFBOID);
952
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000953 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000954 // to one and then resolve to the texture bound to the other.
955 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000956 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000957 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000958 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000959 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
960 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000961 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000962 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000963 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
964 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000965 return return_null_texture();
966 }
967 } else {
968 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
969 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000970 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000971 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000972 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000973 }
974
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000975 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000976 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000977 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000978 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000979
twiz@google.com0f31ca72011-03-18 17:38:11 +0000980 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000981
982 const StencilFormat* stencilFormats = GrGLStencilFormats();
983 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000984 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000985 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000986 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000987 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000988 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000989 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000990 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000991 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000992 glDesc.fAllocWidth,
993 glDesc.fAllocHeight));
994 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000995 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000996 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000997 glDesc.fAllocWidth,
998 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000999 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001000 err = GrGLGetGLInterface()->fGetError();
1001 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001002 continue;
1003 }
1004 }
1005 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
1006 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001007 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001008 rtIDs.fMSColorRenderbufferID));
1009 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001010 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001011 samples,
1012 msColorRenderbufferFormat,
1013 glDesc.fAllocWidth,
1014 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001015 err = GrGLGetGLInterface()->fGetError();
1016 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001017 continue;
1018 }
1019 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001020 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001021
1022#if GR_COLLECT_STATS
1023 ++fStats.fRenderTargetChngCnt;
1024#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001025 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1026 GR_GL_COLOR_ATTACHMENT0,
1027 GR_GL_TEXTURE_2D,
1028 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001029 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001030 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1031 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001032 continue;
1033 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001034 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001035 #if GR_COLLECT_STATS
1036 ++fStats.fRenderTargetChngCnt;
1037 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001038 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1039 GR_GL_COLOR_ATTACHMENT0,
1040 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001041 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001042
1043 }
1044 if (rtIDs.fStencilRenderbufferID) {
1045 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001046 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1047 GR_GL_STENCIL_ATTACHMENT,
1048 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001049 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001050 // if it is a packed format bind to depth also, otherwise
1051 // we may get an unsupported fbo completeness result
1052 if (stencilFormats[i].fPacked) {
1053 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1054 GR_GL_DEPTH_ATTACHMENT,
1055 GR_GL_RENDERBUFFER,
1056 rtIDs.fStencilRenderbufferID));
1057 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001058 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001059 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001060
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001061 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001062 // undo the depth bind
1063 if (rtIDs.fStencilRenderbufferID &&
1064 stencilFormats[i].fPacked) {
1065 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1066 GR_GL_DEPTH_ATTACHMENT,
1067 GR_GL_RENDERBUFFER,
1068 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001069 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001070 continue;
1071 }
1072 // we're successful!
1073 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001074 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001075 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001076 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001077 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001078 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001079 }
1080 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001081 break;
1082 }
1083 if (failed) {
1084 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001085 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001086 }
1087 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001088 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001089 }
1090 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001091 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001092 }
1093 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001094 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001095 }
1096 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1097 return return_null_texture();
1098 }
1099 }
1100#ifdef TRACE_TEXTURE_CREATION
1101 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1102 tex->fTextureID, width, height, tex->fUploadByteCount);
1103#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001104 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001105
1106 if (0 != rtIDs.fTexFBOID) {
1107 GrRenderTarget* rt = tex->asRenderTarget();
1108 // We've messed with FBO state but may not have set the correct viewport
1109 // so just dirty the rendertarget state to force a resend.
1110 fHWDrawState.fRenderTarget = NULL;
1111
1112 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001113 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001114 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1115 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001116 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001117 fCurrDrawState.fRenderTarget = rtSave;
1118 }
1119 }
1120 return tex;
1121}
1122
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001123GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001124 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001125 GR_GL(GenBuffers(1, &id));
1126 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001127 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001128 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001129 GrGLClearErr();
1130 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001131 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1132 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1133 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001134 GR_GL(DeleteBuffers(1, &id));
1135 // deleting bound buffer does implicit bind to 0
1136 fHWGeometryState.fVertexBuffer = NULL;
1137 return NULL;
1138 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001139 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001140 size, dynamic);
1141 fHWGeometryState.fVertexBuffer = vertexBuffer;
1142 return vertexBuffer;
1143 }
1144 return NULL;
1145}
1146
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001147GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001148 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001149 GR_GL(GenBuffers(1, &id));
1150 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001151 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001152 GrGLClearErr();
1153 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001154 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1155 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1156 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001157 GR_GL(DeleteBuffers(1, &id));
1158 // deleting bound buffer does implicit bind to 0
1159 fHWGeometryState.fIndexBuffer = NULL;
1160 return NULL;
1161 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001162 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001163 size, dynamic);
1164 fHWGeometryState.fIndexBuffer = indexBuffer;
1165 return indexBuffer;
1166 }
1167 return NULL;
1168}
1169
reed@google.comac10a2d2010-12-22 21:39:39 +00001170void GrGpuGL::flushScissor(const GrIRect* rect) {
1171 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001172 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001173 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001174
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001175 GrGLIRect scissor;
1176 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001177 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001178 rect->width(), rect->height());
1179 if (scissor.contains(vp)) {
1180 rect = NULL;
1181 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001182 }
1183
1184 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001185 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001186 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001187 fHWBounds.fScissorRect = scissor;
1188 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001189 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001190 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001191 fHWBounds.fScissorEnabled = true;
1192 }
1193 } else {
1194 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001195 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001196 fHWBounds.fScissorEnabled = false;
1197 }
1198 }
1199}
1200
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001201void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001202 if (NULL == fCurrDrawState.fRenderTarget) {
1203 return;
1204 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001205 GrIRect r;
1206 if (NULL != rect) {
1207 // flushScissor expects rect to be clipped to the target.
1208 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001209 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1210 fCurrDrawState.fRenderTarget->height());
1211 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001212 rect = &r;
1213 } else {
1214 return;
1215 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001216 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001217 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001218 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001219 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001220 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001221 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1222 GrColorUnpackG(color)/255.f,
1223 GrColorUnpackB(color)/255.f,
1224 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001225 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001226}
1227
bsalomon@google.com398109c2011-04-14 18:40:27 +00001228void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001229 if (NULL == fCurrDrawState.fRenderTarget) {
1230 return;
1231 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001232
1233 this->flushRenderTarget(&GrIRect::EmptyIRect());
1234
reed@google.comac10a2d2010-12-22 21:39:39 +00001235 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001236 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001237 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001238 }
1239 GR_GL(StencilMask(mask));
1240 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001241 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001242 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001243}
1244
bsalomon@google.com398109c2011-04-14 18:40:27 +00001245void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001246 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001247#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001248 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001249 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001250 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001251#else
1252 // we could just clear the clip bit but when we go through
1253 // angle a partial stencil mask will cause clears to be
1254 // turned into draws. Our contract on GrDrawTarget says that
1255 // changing the clip between stencil passes may or may not
1256 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001257 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001258#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001259 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001260 flushScissor(&rect);
1261 GR_GL(StencilMask(clipStencilMask));
1262 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001263 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001264 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001265}
1266
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001267void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001268 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001269}
1270
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001271bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1272 int left, int top, int width, int height,
1273 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001274 GrGLenum internalFormat; // we don't use this for glReadPixels
1275 GrGLenum format;
1276 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001277 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1278 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001279 }
1280 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1281 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1282 switch (tgt->getResolveType()) {
1283 case GrGLRenderTarget::kCantResolve_ResolveType:
1284 return false;
1285 case GrGLRenderTarget::kAutoResolves_ResolveType:
1286 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1287 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001288 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001289 break;
1290 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001291 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001292 // we don't track the state of the READ FBO ID.
1293 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1294 break;
1295 default:
1296 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001297 }
1298
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001299 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001300
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001301 // the read rect is viewport-relative
1302 GrGLIRect readRect;
1303 readRect.setRelativeTo(glvp, left, top, width, height);
1304 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001305 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001306 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001307
1308 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1309 // API presents top-to-bottom
1310 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001311 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001312 GrAutoMalloc rowStorage(stride);
1313 void* tmp = rowStorage.get();
1314
1315 const int halfY = height >> 1;
1316 char* top = reinterpret_cast<char*>(buffer);
1317 char* bottom = top + (height - 1) * stride;
1318 for (int y = 0; y < halfY; y++) {
1319 memcpy(tmp, top, stride);
1320 memcpy(top, bottom, stride);
1321 memcpy(bottom, tmp, stride);
1322 top += stride;
1323 bottom -= stride;
1324 }
1325 }
1326 return true;
1327}
1328
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001329void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001330
1331 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1332
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001333 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001334 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001335 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001336 #if GR_COLLECT_STATS
1337 ++fStats.fRenderTargetChngCnt;
1338 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001339 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001340 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1341 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001342 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001343 }
1344 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001345 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001346 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001347 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001348 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001349 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001350 fHWBounds.fViewportRect = vp;
1351 }
1352 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001353 if (NULL == bound || !bound->isEmpty()) {
1354 rt->flagAsNeedingResolve(bound);
1355 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001356}
1357
twiz@google.com0f31ca72011-03-18 17:38:11 +00001358GrGLenum gPrimitiveType2GLMode[] = {
1359 GR_GL_TRIANGLES,
1360 GR_GL_TRIANGLE_STRIP,
1361 GR_GL_TRIANGLE_FAN,
1362 GR_GL_POINTS,
1363 GR_GL_LINES,
1364 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001365};
1366
bsalomon@google.comd302f142011-03-03 13:54:13 +00001367#define SWAP_PER_DRAW 0
1368
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001369#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001370 #if GR_MAC_BUILD
1371 #include <AGL/agl.h>
1372 #elif GR_WIN32_BUILD
1373 void SwapBuf() {
1374 DWORD procID = GetCurrentProcessId();
1375 HWND hwnd = GetTopWindow(GetDesktopWindow());
1376 while(hwnd) {
1377 DWORD wndProcID = 0;
1378 GetWindowThreadProcessId(hwnd, &wndProcID);
1379 if(wndProcID == procID) {
1380 SwapBuffers(GetDC(hwnd));
1381 }
1382 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1383 }
1384 }
1385 #endif
1386#endif
1387
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001388void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1389 uint32_t startVertex,
1390 uint32_t startIndex,
1391 uint32_t vertexCount,
1392 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001393 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1394
twiz@google.com0f31ca72011-03-18 17:38:11 +00001395 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001396
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001397 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1398 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1399
1400 // our setupGeometry better have adjusted this to zero since
1401 // DrawElements always draws from the begining of the arrays for idx 0.
1402 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001403
1404 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001405 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001406#if SWAP_PER_DRAW
1407 glFlush();
1408 #if GR_MAC_BUILD
1409 aglSwapBuffers(aglGetCurrentContext());
1410 int set_a_break_pt_here = 9;
1411 aglSwapBuffers(aglGetCurrentContext());
1412 #elif GR_WIN32_BUILD
1413 SwapBuf();
1414 int set_a_break_pt_here = 9;
1415 SwapBuf();
1416 #endif
1417#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001418}
1419
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001420void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1421 uint32_t startVertex,
1422 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001423 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1424
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001425 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1426
1427 // our setupGeometry better have adjusted this to zero.
1428 // DrawElements doesn't take an offset so we always adjus the startVertex.
1429 GrAssert(0 == startVertex);
1430
1431 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1432 // account for startVertex in the DrawElements case. So we always
1433 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001434 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001435#if SWAP_PER_DRAW
1436 glFlush();
1437 #if GR_MAC_BUILD
1438 aglSwapBuffers(aglGetCurrentContext());
1439 int set_a_break_pt_here = 9;
1440 aglSwapBuffers(aglGetCurrentContext());
1441 #elif GR_WIN32_BUILD
1442 SwapBuf();
1443 int set_a_break_pt_here = 9;
1444 SwapBuf();
1445 #endif
1446#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001447}
1448
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001449void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001450
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001451 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001452 GrAssert(kNone_MSFBO != fMSFBOType);
1453 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001454 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001455 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001456 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001457 rt->textureFBOID()));
1458 #if GR_COLLECT_STATS
1459 ++fStats.fRenderTargetChngCnt;
1460 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001461 // make sure we go through flushRenderTarget() since we've modified
1462 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001463 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001464 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001465 const GrIRect dirtyRect = rt->getResolveRect();
1466 GrGLIRect r;
1467 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1468 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001469
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001470 if (kAppleES_MSFBO == fMSFBOType) {
1471 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001472 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001473 GR_GL(Scissor(r.fLeft, r.fBottom,
1474 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001475 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001476 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001477 fHWBounds.fScissorEnabled = true;
1478 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001479 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001480 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001481 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1482 flushScissor(NULL);
1483 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001484 int right = r.fLeft + r.fWidth;
1485 int top = r.fBottom + r.fHeight;
1486 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1487 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001488 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001489 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001490 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001491 }
1492}
1493
twiz@google.com0f31ca72011-03-18 17:38:11 +00001494static const GrGLenum grToGLStencilFunc[] = {
1495 GR_GL_ALWAYS, // kAlways_StencilFunc
1496 GR_GL_NEVER, // kNever_StencilFunc
1497 GR_GL_GREATER, // kGreater_StencilFunc
1498 GR_GL_GEQUAL, // kGEqual_StencilFunc
1499 GR_GL_LESS, // kLess_StencilFunc
1500 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1501 GR_GL_EQUAL, // kEqual_StencilFunc,
1502 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001503};
1504GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1505GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1506GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1507GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1508GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1509GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1510GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1511GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1512GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1513
twiz@google.com0f31ca72011-03-18 17:38:11 +00001514static const GrGLenum grToGLStencilOp[] = {
1515 GR_GL_KEEP, // kKeep_StencilOp
1516 GR_GL_REPLACE, // kReplace_StencilOp
1517 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1518 GR_GL_INCR, // kIncClamp_StencilOp
1519 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1520 GR_GL_DECR, // kDecClamp_StencilOp
1521 GR_GL_ZERO, // kZero_StencilOp
1522 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001523};
1524GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1525GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1526GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1527GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1528GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1529GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1530GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1531GR_STATIC_ASSERT(6 == kZero_StencilOp);
1532GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1533
reed@google.comac10a2d2010-12-22 21:39:39 +00001534void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001535 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001536
1537 // use stencil for clipping if clipping is enabled and the clip
1538 // has been written into the stencil.
1539 bool stencilClip = fClipState.fClipInStencil &&
1540 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001541 bool stencilChange = fHWStencilClip != stencilClip ||
1542 fHWDrawState.fStencilSettings != *settings ||
1543 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1544 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001545
1546 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001547
bsalomon@google.comd302f142011-03-03 13:54:13 +00001548 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1549 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001550
bsalomon@google.comd302f142011-03-03 13:54:13 +00001551 if (settings->isDisabled()) {
1552 if (stencilClip) {
1553 settings = &gClipStencilSettings;
1554 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001555 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001556
1557 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001558 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001559 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001560 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001561 #if GR_DEBUG
1562 if (!fStencilWrapOpsSupport) {
1563 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1564 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1565 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1566 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1567 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1568 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1569 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1570 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1571 }
1572 #endif
1573 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1574 GrAssert(stencilBits ||
1575 (GrStencilSettings::gDisabled ==
1576 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001577 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1578 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001579
1580 unsigned int frontRef = settings->fFrontFuncRef;
1581 unsigned int frontMask = settings->fFrontFuncMask;
1582 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001583 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001584
1585 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1586
1587 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1588 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1589 } else {
1590 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1591
1592 ConvertStencilFuncAndMask(settings->fFrontFunc,
1593 stencilClip,
1594 clipStencilMask,
1595 userStencilMask,
1596 &frontRef,
1597 &frontMask);
1598 frontWriteMask &= userStencilMask;
1599 }
1600 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001601 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001602 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001603 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001604 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001605 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001606 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001607 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001608 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001609 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001610
1611 unsigned int backRef = settings->fBackFuncRef;
1612 unsigned int backMask = settings->fBackFuncMask;
1613 unsigned int backWriteMask = settings->fBackWriteMask;
1614
1615
1616 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1617 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1618 backFunc = grToGLStencilFunc[settings->fBackFunc];
1619 } else {
1620 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1621 ConvertStencilFuncAndMask(settings->fBackFunc,
1622 stencilClip,
1623 clipStencilMask,
1624 userStencilMask,
1625 &backRef,
1626 &backMask);
1627 backWriteMask &= userStencilMask;
1628 }
1629
twiz@google.com0f31ca72011-03-18 17:38:11 +00001630 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1631 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1632 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1633 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1634 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001635 grToGLStencilOp[settings->fFrontPassOp],
1636 grToGLStencilOp[settings->fFrontPassOp]));
1637
twiz@google.com0f31ca72011-03-18 17:38:11 +00001638 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001639 grToGLStencilOp[settings->fBackPassOp],
1640 grToGLStencilOp[settings->fBackPassOp]));
1641 } else {
1642 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1643 GR_GL(StencilMask(frontWriteMask));
1644 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1645 grToGLStencilOp[settings->fFrontPassOp],
1646 grToGLStencilOp[settings->fFrontPassOp]));
1647 }
1648 }
1649 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001650 fHWStencilClip = stencilClip;
1651 }
1652}
1653
bsalomon@google.com0650e812011-04-08 18:07:53 +00001654bool GrGpuGL::useSmoothLines() {
1655 // there is a conflict between using smooth lines and our use of
1656 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1657 // but not in a premul-alpha way. So we only use them when our alpha
1658 // is 0xff.
1659
1660 // TODO: write a smarter line frag shader.
1661
1662 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1663 canDisableBlend();
1664}
1665
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001666void GrGpuGL::flushAAState(GrPrimitiveType type) {
1667 if (GR_GL_SUPPORT_DESKTOP) {
1668 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1669 // smooth lines.
1670
1671 // we prefer smooth lines over multisampled lines
1672 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001673 if (GrIsPrimTypeLines(type)) {
1674 bool smooth = useSmoothLines();
1675 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001676 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1677 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001678 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001679 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1680 fHWAAState.fSmoothLineEnabled = false;
1681 }
1682 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1683 fHWAAState.fMSAAEnabled) {
1684 GR_GL(Disable(GR_GL_MULTISAMPLE));
1685 fHWAAState.fMSAAEnabled = false;
1686 }
1687 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1688 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1689 fHWAAState.fMSAAEnabled) {
1690 if (fHWAAState.fMSAAEnabled) {
1691 GR_GL(Disable(GR_GL_MULTISAMPLE));
1692 fHWAAState.fMSAAEnabled = false;
1693 } else {
1694 GR_GL(Enable(GR_GL_MULTISAMPLE));
1695 fHWAAState.fMSAAEnabled = true;
1696 }
1697 }
1698 }
1699}
1700
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001701void GrGpuGL::flushBlend(GrPrimitiveType type,
1702 GrBlendCoeff srcCoeff,
1703 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001704 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1705 if (fHWBlendDisabled) {
1706 GR_GL(Enable(GR_GL_BLEND));
1707 fHWBlendDisabled = false;
1708 }
1709 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1710 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1711 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1712 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1713 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1714 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1715 }
1716 } else {
1717 bool blendOff = canDisableBlend();
1718 if (fHWBlendDisabled != blendOff) {
1719 if (blendOff) {
1720 GR_GL(Disable(GR_GL_BLEND));
1721 } else {
1722 GR_GL(Enable(GR_GL_BLEND));
1723 }
1724 fHWBlendDisabled = blendOff;
1725 }
1726 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001727 if (fHWDrawState.fSrcBlend != srcCoeff ||
1728 fHWDrawState.fDstBlend != dstCoeff) {
1729 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1730 gXfermodeCoeff2Blend[dstCoeff]));
1731 fHWDrawState.fSrcBlend = srcCoeff;
1732 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001733 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001734 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1735 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001736 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1737
1738 float c[] = {
1739 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1740 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1741 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1742 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1743 };
1744 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1745 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1746 }
1747 }
1748 }
1749}
1750
bsalomon@google.comffca4002011-02-22 20:34:01 +00001751bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001752
1753 // GrGpu::setupClipAndFlushState should have already checked this
1754 // and bailed if not true.
1755 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001756
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001757 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001758 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001759 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001760 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001761
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001762 // true for now, but maybe not with GrEffect.
1763 GrAssert(NULL != nextTexture);
1764 // if we created a rt/tex and rendered to it without using a
1765 // texture and now we're texuring from the rt it will still be
1766 // the last bound texture, but it needs resolving. So keep this
1767 // out of the "last != next" check.
1768 GrGLRenderTarget* texRT =
1769 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1770 if (NULL != texRT) {
1771 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001772 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001773
1774 if (fHWDrawState.fTextures[s] != nextTexture) {
1775 setTextureUnit(s);
1776 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1777 #if GR_COLLECT_STATS
1778 ++fStats.fTextureChngCnt;
1779 #endif
1780 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1781 fHWDrawState.fTextures[s] = nextTexture;
bsalomon@google.comcd19a5f2011-06-15 14:00:23 +00001782 // The texture matrix has to compensate for texture width/height
1783 // and NPOT-embedded-in-POT
1784 fDirtyFlags.fTextureChangedMask |= (1 << s);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001785 }
1786
1787 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1788 const GrGLTexture::TexParams& oldTexParams =
1789 nextTexture->getTexParams();
1790 GrGLTexture::TexParams newTexParams;
1791
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001792 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1793 newTexParams.fFilter = GR_GL_NEAREST;
1794 } else {
1795 newTexParams.fFilter = GR_GL_LINEAR;
1796 }
1797
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001798 newTexParams.fWrapS =
1799 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1800 newTexParams.fWrapT =
1801 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1802
1803 if (newTexParams.fFilter != oldTexParams.fFilter) {
1804 setTextureUnit(s);
1805 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1806 GR_GL_TEXTURE_MAG_FILTER,
1807 newTexParams.fFilter));
1808 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1809 GR_GL_TEXTURE_MIN_FILTER,
1810 newTexParams.fFilter));
1811 }
1812 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1813 setTextureUnit(s);
1814 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1815 GR_GL_TEXTURE_WRAP_S,
1816 newTexParams.fWrapS));
1817 }
1818 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1819 setTextureUnit(s);
1820 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1821 GR_GL_TEXTURE_WRAP_T,
1822 newTexParams.fWrapT));
1823 }
1824 nextTexture->setTexParams(newTexParams);
reed@google.comac10a2d2010-12-22 21:39:39 +00001825 }
1826 }
1827
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001828 GrIRect* rect = NULL;
1829 GrIRect clipBounds;
1830 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1831 fClip.hasConservativeBounds()) {
1832 fClip.getConservativeBounds().roundOut(&clipBounds);
1833 rect = &clipBounds;
1834 }
1835 this->flushRenderTarget(rect);
1836 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001837
reed@google.comac10a2d2010-12-22 21:39:39 +00001838 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1839 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1840 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001841 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001842 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001843 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001844 }
1845 }
1846
bsalomon@google.comd302f142011-03-03 13:54:13 +00001847 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1848 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001849 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001850 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001851 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001852 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001853 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001854 }
1855 GR_GL(ColorMask(mask, mask, mask, mask));
1856 }
1857
bsalomon@google.comd302f142011-03-03 13:54:13 +00001858 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1859 switch (fCurrDrawState.fDrawFace) {
1860 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001861 GR_GL(Enable(GR_GL_CULL_FACE));
1862 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001863 break;
1864 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001865 GR_GL(Enable(GR_GL_CULL_FACE));
1866 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001867 break;
1868 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001869 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001870 break;
1871 default:
1872 GrCrash("Unknown draw face.");
1873 }
1874 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1875 }
1876
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001877#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001878 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001879 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001880 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001881 NULL == fCurrDrawState.fRenderTarget ||
1882 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001883 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001884 fCurrDrawState.fRenderTarget);
1885 }
1886#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001887
reed@google.comac10a2d2010-12-22 21:39:39 +00001888 flushStencil();
1889
bsalomon@google.comd302f142011-03-03 13:54:13 +00001890 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001891 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001892 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001893}
1894
1895void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001896 if (fHWGeometryState.fVertexBuffer != buffer) {
1897 fHWGeometryState.fArrayPtrsDirty = true;
1898 fHWGeometryState.fVertexBuffer = buffer;
1899 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001900}
1901
1902void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001903 if (fHWGeometryState.fVertexBuffer == buffer) {
1904 // deleting bound buffer does implied bind to 0
1905 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001906 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001907 }
1908}
1909
1910void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1911 fGeometrySrc.fIndexBuffer = buffer;
1912}
1913
1914void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001915 if (fHWGeometryState.fIndexBuffer == buffer) {
1916 // deleting bound buffer does implied bind to 0
1917 fHWGeometryState.fIndexBuffer = NULL;
1918 }
1919}
1920
reed@google.comac10a2d2010-12-22 21:39:39 +00001921void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1922 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001923 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001924 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001925 }
1926 if (fHWDrawState.fRenderTarget == renderTarget) {
1927 fHWDrawState.fRenderTarget = NULL;
1928 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001929}
1930
1931void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001932 for (int s = 0; s < kNumStages; ++s) {
1933 if (fCurrDrawState.fTextures[s] == texture) {
1934 fCurrDrawState.fTextures[s] = NULL;
1935 }
1936 if (fHWDrawState.fTextures[s] == texture) {
1937 // deleting bound texture does implied bind to 0
1938 fHWDrawState.fTextures[s] = NULL;
1939 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001940 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001941}
1942
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001943bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001944 GrGLenum* internalFormat,
1945 GrGLenum* format,
1946 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001947 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001948 case kRGBA_8888_GrPixelConfig:
1949 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001950 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001951 if (GR_GL_SUPPORT_ES) {
1952 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1953 // format for a BGRA is BGRA not RGBA (as on desktop)
1954 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1955 } else {
1956 *internalFormat = GR_GL_RGBA;
1957 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001958 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001959 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001960 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001961 *format = GR_GL_RGB;
1962 *internalFormat = GR_GL_RGB;
1963 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001964 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001965 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001966 *format = GR_GL_RGBA;
1967 *internalFormat = GR_GL_RGBA;
1968 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001969 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001970 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001971 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001972 *format = GR_GL_PALETTE8_RGBA8;
1973 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001974 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001975 } else {
1976 return false;
1977 }
1978 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001979 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001980 *format = GR_GL_ALPHA;
1981 *internalFormat = GR_GL_ALPHA;
1982 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001983 break;
1984 default:
1985 return false;
1986 }
1987 return true;
1988}
1989
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001990void GrGpuGL::setTextureUnit(int unit) {
1991 GrAssert(unit >= 0 && unit < kNumStages);
1992 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001993 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001994 fActiveTextureUnitIdx = unit;
1995 }
1996}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001997
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001998void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001999 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
2000 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00002001 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
2002 }
2003}
2004
reed@google.comac10a2d2010-12-22 21:39:39 +00002005/* On ES the internalFormat and format must match for TexImage and we use
2006 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
2007 decide the internalFormat. However, on ES internalFormat for
2008 RenderBufferStorage* has to be a specific format (not a base format like
2009 GL_RGBA).
2010 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002011bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00002012 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002013 case kRGBA_8888_GrPixelConfig:
2014 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00002015 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002016 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00002017 return true;
2018 } else {
2019 return false;
2020 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002021 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002022 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2023 // with FBO extension desktop GL has
2024 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002025 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002026 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002027 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002028 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002029 return true;
2030 default:
2031 return false;
2032 }
2033}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002034
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002035void GrGpuGL::resetDirtyFlags() {
2036 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2037}
2038
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002039void GrGpuGL::setBuffers(bool indexed,
2040 int* extraVertexOffset,
2041 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002042
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002043 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002044
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002045 GrGLVertexBuffer* vbuf;
2046 switch (fGeometrySrc.fVertexSrc) {
2047 case kBuffer_GeometrySrcType:
2048 *extraVertexOffset = 0;
2049 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2050 break;
2051 case kArray_GeometrySrcType:
2052 case kReserved_GeometrySrcType:
2053 finalizeReservedVertices();
2054 *extraVertexOffset = fCurrPoolStartVertex;
2055 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2056 break;
2057 default:
2058 vbuf = NULL; // suppress warning
2059 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002060 }
2061
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002062 GrAssert(NULL != vbuf);
2063 GrAssert(!vbuf->isLocked());
2064 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002065 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002066 fHWGeometryState.fArrayPtrsDirty = true;
2067 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002068 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002069
2070 if (indexed) {
2071 GrAssert(NULL != extraIndexOffset);
2072
2073 GrGLIndexBuffer* ibuf;
2074 switch (fGeometrySrc.fIndexSrc) {
2075 case kBuffer_GeometrySrcType:
2076 *extraIndexOffset = 0;
2077 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2078 break;
2079 case kArray_GeometrySrcType:
2080 case kReserved_GeometrySrcType:
2081 finalizeReservedIndices();
2082 *extraIndexOffset = fCurrPoolStartIndex;
2083 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2084 break;
2085 default:
2086 ibuf = NULL; // suppress warning
2087 GrCrash("Unknown geometry src type!");
2088 }
2089
2090 GrAssert(NULL != ibuf);
2091 GrAssert(!ibuf->isLocked());
2092 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002093 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002094 fHWGeometryState.fIndexBuffer = ibuf;
2095 }
2096 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002097}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002098
2099int GrGpuGL::getMaxEdges() const {
2100 // FIXME: This is a pessimistic estimate based on how many other things
2101 // want to add uniforms. This should be centralized somewhere.
2102 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2103}