blob: ff2d406e3d17d668961df8221983a5f90b63a0df [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
reed@google.comac10a2d2010-12-22 21:39:39 +0000192GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000193
reed@google.comeeeb5a02010-12-23 15:12:59 +0000194 if (gPrintStartupSpew) {
195 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
196 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000197 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000198 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000199 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000200 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000201 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000202 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000203 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000204 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000205 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000206
207 GrGLClearErr();
208
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000209 resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000210
twiz@google.com0f31ca72011-03-18 17:38:11 +0000211 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000212 // check FS and fixed-function texture unit limits
213 // we only use textures in the fragment stage currently.
214 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000215 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
216 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
217 GrAssert(maxTextureUnits > kNumStages);
218 }
219 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
220 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
221 GrAssert(maxTextureUnits > kNumStages);
222 }
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000223 if (GR_GL_SUPPORT_ES2) {
224 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
225 &fMaxFragmentUniformVectors);
226 } else if (GR_GL_SUPPORT_DESKTOP) {
227 GrGLint max;
228 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
229 fMaxFragmentUniformVectors = max / 4;
230 } else {
231 fMaxFragmentUniformVectors = 16;
232 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000233
reed@google.comac10a2d2010-12-22 21:39:39 +0000234 ////////////////////////////////////////////////////////////////////////////
235 // Check for supported features.
236
237 int major, minor;
238 gl_version(&major, &minor);
239
twiz@google.com0f31ca72011-03-18 17:38:11 +0000240 GrGLint numFormats;
241 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
242 GrAutoSTMalloc<10, GrGLint> formats(numFormats);
243 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000244 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000245 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000246 f8bitPaletteSupport = true;
247 break;
248 }
249 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000250
251 if (gPrintStartupSpew) {
252 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
253 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000254
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000255 GR_STATIC_ASSERT(0 == kNone_GrAALevel);
256 GR_STATIC_ASSERT(1 == kLow_GrAALevel);
257 GR_STATIC_ASSERT(2 == kMed_GrAALevel);
258 GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
reed@google.comac10a2d2010-12-22 21:39:39 +0000259
260 memset(fAASamples, 0, sizeof(fAASamples));
261 fMSFBOType = kNone_MSFBO;
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000262 if (GR_GL_SUPPORT_ES) {
263 if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000264 // chrome's extension is equivalent to the EXT msaa
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000265 // and fbo_blit extensions.
266 fMSFBOType = kDesktopEXT_MSFBO;
267 } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
268 fMSFBOType = kAppleES_MSFBO;
269 }
270 } else {
271 GrAssert(GR_GL_SUPPORT_DESKTOP);
272 if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
273 fMSFBOType = kDesktopARB_MSFBO;
274 } else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
275 has_gl_extension("GL_EXT_framebuffer_blit")) {
276 fMSFBOType = kDesktopEXT_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000277 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000278 }
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000279 if (gPrintStartupSpew) {
280 switch (fMSFBOType) {
281 case kNone_MSFBO:
282 GrPrintf("MSAA Support: NONE\n");
283 break;
284 case kDesktopARB_MSFBO:
285 GrPrintf("MSAA Support: DESKTOP ARB.\n");
286 break;
287 case kDesktopEXT_MSFBO:
288 GrPrintf("MSAA Support: DESKTOP EXT.\n");
289 break;
290 case kAppleES_MSFBO:
291 GrPrintf("MSAA Support: APPLE ES.\n");
292 break;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000293 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000294 }
295
296 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000297 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000298 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000299 if (maxSamples > 1 ) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000300 fAASamples[kNone_GrAALevel] = 0;
301 fAASamples[kLow_GrAALevel] = GrMax(2,
302 GrFixedFloorToInt((GR_FixedHalf) *
303 maxSamples));
304 fAASamples[kMed_GrAALevel] = GrMax(2,
305 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
306 maxSamples));
307 fAASamples[kHigh_GrAALevel] = maxSamples;
reed@google.comac10a2d2010-12-22 21:39:39 +0000308 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000309 if (gPrintStartupSpew) {
310 GrPrintf("\tMax Samples: %d\n", maxSamples);
311 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000312 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +0000313 fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000314
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000315 if (GR_GL_SUPPORT_DESKTOP) {
316 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
317 has_gl_extension("GL_EXT_stencil_wrap");
318 } else {
319 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
320 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000321 if (gPrintStartupSpew) {
322 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
323 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000324
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000325 if (GR_GL_SUPPORT_DESKTOP) {
326 // we could also look for GL_ATI_separate_stencil extension or
327 // GL_EXT_stencil_two_side but they use different function signatures
328 // than GL2.0+ (and than each other).
329 fTwoSidedStencilSupport = (major >= 2);
330 // supported on GL 1.4 and higher or by extension
331 fStencilWrapOpsSupport = (major > 1) ||
332 ((1 == major) && (minor >= 4)) ||
333 has_gl_extension("GL_EXT_stencil_wrap");
334 } else {
335 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
336 // an ES1 extension.
337 fTwoSidedStencilSupport = (major >= 2);
338 // stencil wrap support is in ES2, ES1 requires extension.
339 fStencilWrapOpsSupport = (major > 1) ||
340 has_gl_extension("GL_OES_stencil_wrap");
341 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000342 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000343 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
344 (fTwoSidedStencilSupport ? "YES" : "NO"),
345 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000346 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000347
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000348 if (GR_GL_SUPPORT_DESKTOP) {
349 fRGBA8Renderbuffer = true;
350 } else {
351 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
352 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000353 if (gPrintStartupSpew) {
354 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
355 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000356
357
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000358 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000359 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000360 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
361 }
362 }
363
364 if (GR_GL_SUPPORT_DESKTOP) {
365 fBufferLockSupport = true; // we require VBO support and the desktop VBO
366 // extension includes glMapBuffer.
367 } else {
368 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
369 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000370
reed@google.comeeeb5a02010-12-23 15:12:59 +0000371 if (gPrintStartupSpew) {
372 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
373 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000374
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000375 if (GR_GL_SUPPORT_DESKTOP) {
376 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
377 fNPOTTextureTileSupport = true;
378 fNPOTTextureSupport = true;
379 } else {
380 fNPOTTextureTileSupport = false;
381 fNPOTTextureSupport = false;
382 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000383 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000384 if (major >= 2) {
385 fNPOTTextureSupport = true;
386 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
387 } else {
388 fNPOTTextureSupport =
389 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
390 fNPOTTextureTileSupport = false;
391 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000392 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000393
bsalomon@google.com205d4602011-04-25 12:43:45 +0000394 fAALineSupport = GR_GL_SUPPORT_DESKTOP;
395
reed@google.comac10a2d2010-12-22 21:39:39 +0000396 ////////////////////////////////////////////////////////////////////////////
397 // Experiments to determine limitations that can't be queried. TODO: Make
398 // these a preprocess that generate some compile time constants.
399
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000400 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000401
twiz@google.com59a190b2011-03-14 21:23:01 +0000402 bool simpleFBOSuccess = fbo_test(128, 128);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000403 if (gPrintStartupSpew) {
404 if (!simpleFBOSuccess) {
405 GrPrintf("FBO Sanity Test: FAILED\n");
406 } else {
407 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000408 }
409 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000410 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000411
reed@google.comac10a2d2010-12-22 21:39:39 +0000412 /* Experimentation has found that some GLs that support NPOT textures
413 do not support FBOs with a NPOT texture. They report "unsupported" FBO
414 status. I don't know how to explicitly query for this. Do an
415 experiment. Note they may support NPOT with a renderbuffer but not a
416 texture. Presumably, the implementation bloats the renderbuffer
417 internally to the next POT.
418 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000419 bool fNPOTRenderTargetSupport = false;
420 if (fNPOTTextureSupport) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000421 fNPOTRenderTargetSupport = fbo_test(200, 200);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000422 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000423
bsalomon@google.com0748f212011-02-01 22:56:16 +0000424 if (gPrintStartupSpew) {
425 if (fNPOTTextureSupport) {
426 GrPrintf("NPOT textures supported\n");
427 if (fNPOTTextureTileSupport) {
428 GrPrintf("NPOT texture tiling supported\n");
429 } else {
430 GrPrintf("NPOT texture tiling NOT supported\n");
431 }
432 if (fNPOTRenderTargetSupport) {
433 GrPrintf("NPOT render targets supported\n");
434 } else {
435 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000436 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000437 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000438 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000439 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000440 }
441
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000442 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
443
reed@google.comac10a2d2010-12-22 21:39:39 +0000444 /* The iPhone 4 has a restriction that for an FBO with texture color
445 attachment with height <= 8 then the width must be <= height. Here
446 we look for such a limitation.
447 */
448 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000449 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000450 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000451 // fbo_test creates FBOs with texture bound to the color attachment
452 maxRenderSize = GrMin(maxRenderSize, fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000453
reed@google.comeeeb5a02010-12-23 15:12:59 +0000454 if (gPrintStartupSpew) {
455 GrPrintf("Small height FBO texture experiments\n");
456 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000457
twiz@google.com0f31ca72011-03-18 17:38:11 +0000458 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
459 GrGLuint w = maxRenderSize;
460 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000461 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000462 if (gPrintStartupSpew) {
463 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
464 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000465 fMinRenderTargetHeight = i;
466 break;
467 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000468 if (gPrintStartupSpew) {
469 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
470 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000471 }
472 }
473 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
474
reed@google.comeeeb5a02010-12-23 15:12:59 +0000475 if (gPrintStartupSpew) {
476 GrPrintf("Small width FBO texture experiments\n");
477 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000478 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000479 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
480 GrGLuint w = i;
481 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000482 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000483 if (gPrintStartupSpew) {
484 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
485 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000486 fMinRenderTargetWidth = i;
487 break;
488 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000489 if (gPrintStartupSpew) {
490 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
491 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000492 }
493 }
494 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
reed@google.comac10a2d2010-12-22 21:39:39 +0000495}
496
497GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000498}
499
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000500void GrGpuGL::resetContext() {
501 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000502 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000503 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000504
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000505 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000506 GR_GL(Disable(GR_GL_DEPTH_TEST));
507 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000508
twiz@google.com0f31ca72011-03-18 17:38:11 +0000509 GR_GL(Disable(GR_GL_CULL_FACE));
510 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000511 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000512
twiz@google.com0f31ca72011-03-18 17:38:11 +0000513 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000514 if (GR_GL_SUPPORT_DESKTOP) {
515 GR_GL(Disable(GR_GL_LINE_SMOOTH));
516 GR_GL(Disable(GR_GL_POINT_SMOOTH));
517 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000518 fHWAAState.fMSAAEnabled = false;
519 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000520 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000521
twiz@google.com0f31ca72011-03-18 17:38:11 +0000522 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000523 fHWDrawState.fFlagBits = 0;
524
reed@google.comac10a2d2010-12-22 21:39:39 +0000525 // we only ever use lines in hairline mode
526 GR_GL(LineWidth(1));
527
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000528 // invalid
529 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000530
reed@google.comac10a2d2010-12-22 21:39:39 +0000531 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000532 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
533 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000534
535 fHWDrawState.fBlendConstant = 0x00000000;
536 GR_GL(BlendColor(0,0,0,0));
537
reed@google.comac10a2d2010-12-22 21:39:39 +0000538 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000539
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000540 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000541
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000542 for (int s = 0; s < kNumStages; ++s) {
543 fHWDrawState.fTextures[s] = NULL;
544 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
545 -GR_ScalarMax,
546 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000547
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000548 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000549 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000550
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000551 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000552 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000553 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000554 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000555
bsalomon@google.comd302f142011-03-03 13:54:13 +0000556 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000557 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000558 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000559
560 fHWGeometryState.fIndexBuffer = NULL;
561 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000562
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000563 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000564
twiz@google.com0f31ca72011-03-18 17:38:11 +0000565 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000566 fHWDrawState.fRenderTarget = NULL;
567}
568
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000569GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
570
571 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
572 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
573 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
574 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
575
576 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
577 if (isRenderTarget) {
578 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
579 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
580 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
581 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
582 } else {
583 GrAssert(!isTexture); // this should have been filtered by GrContext
584 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
585 }
586 } else {
587 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
588 }
589 // we don't know what the RB ids are without glGets and we don't care
590 // since we aren't responsible for deleting them.
591 rtIDs.fStencilRenderbufferID = 0;
592 rtIDs.fMSColorRenderbufferID = 0;
593
594 rtIDs.fOwnIDs = false;
595 } else {
596 rtIDs.reset();
597 }
598
599 if (isTexture) {
600 GrGLTexture::GLTextureDesc texDesc;
601 GrGLenum dontCare;
602 if (!canBeTexture(desc.fConfig, &dontCare,
603 &texDesc.fUploadFormat,
604 &texDesc.fUploadType)) {
605 return NULL;
606 }
607
608 GrGLTexture::TexParams params;
609
610 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
611 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
612
613 texDesc.fFormat = texDesc.fFormat;
614 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
615 texDesc.fStencilBits = desc.fStencilBits;
616 texDesc.fTextureID = desc.fPlatformTexture;
617 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
618 texDesc.fOwnsID = false;
619
620 params.invalidate(); // rather than do glGets.
621
622 return new GrGLTexture(this, texDesc, rtIDs, params);
623 } else {
624 GrGLIRect viewport;
625 viewport.fLeft = 0;
626 viewport.fBottom = 0;
627 viewport.fWidth = desc.fWidth;
628 viewport.fHeight = desc.fHeight;
629
630 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
631 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
632 viewport, NULL);
633 }
634}
635
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000636GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000637
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000638 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000639
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000640 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000641 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
642 rtIDs.fMSColorRenderbufferID = 0;
643 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000644
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000645 GrGLIRect viewport;
646 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000647 GrGLuint stencilBits;
648 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000649
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000650 GrGLint samples;
651 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
652
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000653 rtIDs.fOwnIDs = false;
654
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000655 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
656 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000657}
658
bsalomon@google.com5782d712011-01-21 21:03:59 +0000659///////////////////////////////////////////////////////////////////////////////
660
twiz@google.com0f31ca72011-03-18 17:38:11 +0000661static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000662
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000663struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000664 GrGLenum fEnum;
665 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000666 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000667};
668
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000669const StencilFormat* GrGLStencilFormats() {
670 // defines stencil formats from more to less preferred
671 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000672 {GR_GL_STENCIL_INDEX8, 8, false},
673 {GR_GL_STENCIL_INDEX16, 16, false},
674 {GR_GL_DEPTH24_STENCIL8, 8, true },
675 {GR_GL_STENCIL_INDEX4, 4, false},
676 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
677 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
678 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000679 };
680
681 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000682 {GR_GL_STENCIL_INDEX8, 8, false},
683 {GR_GL_DEPTH24_STENCIL8, 8, true },
684 {GR_GL_STENCIL_INDEX4, 4, false},
685 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000686 };
687
688 if (GR_GL_SUPPORT_DESKTOP) {
689 return desktopStencilFormats;
690 } else {
691 return esStencilFormats;
692 }
693}
694
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000695// good to set a break-point here to know when createTexture fails
696static GrTexture* return_null_texture() {
697// GrAssert(!"null texture");
698 return NULL;
699}
700
701#if GR_DEBUG
702static size_t as_size_t(int x) {
703 return x;
704}
705#endif
706
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000707GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000708 const void* srcData,
709 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000710
711#if GR_COLLECT_STATS
712 ++fStats.fTextureCreateCnt;
713#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000714
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000715 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000716
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000717 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000718 GR_GL_NEAREST,
719 GR_GL_CLAMP_TO_EDGE,
720 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000721 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000722
reed@google.comac10a2d2010-12-22 21:39:39 +0000723 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000724 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000725
726 glDesc.fContentWidth = desc.fWidth;
727 glDesc.fContentHeight = desc.fHeight;
728 glDesc.fAllocWidth = desc.fWidth;
729 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000730 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000731 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000732 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000733
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000734 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000735 if (!canBeTexture(desc.fFormat,
736 &internalFormat,
737 &glDesc.fUploadFormat,
738 &glDesc.fUploadType)) {
739 return return_null_texture();
740 }
741
742 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000743 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000744 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000745 GrPrintf("AA RT requested but not supported on this platform.");
746 }
747
748 GR_GL(GenTextures(1, &glDesc.fTextureID));
749 if (!glDesc.fTextureID) {
750 return return_null_texture();
751 }
752
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000753 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000754
reed@google.com5e762232011-04-04 18:15:49 +0000755 // in case we need a temporary, trimmed copy of the src pixels
756 GrAutoSMalloc<128 * 128> trimStorage;
757
reed@google.comac10a2d2010-12-22 21:39:39 +0000758 /*
759 * check if our srcData has extra bytes past each row. If so, we need
760 * to trim those off here, since GL doesn't let us pass the rowBytes as
761 * a parameter to glTexImage2D
762 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000763 if (GR_GL_SUPPORT_DESKTOP) {
764 if (srcData) {
765 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
766 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000767 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000768 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000769 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
770 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000771 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000772 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000773 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000774 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000775 for (uint32_t y = 0; y < desc.fHeight; y++) {
776 memcpy(dst, src, trimRowBytes);
777 src += rowBytes;
778 dst += trimRowBytes;
779 }
780 // now point srcData to our trimmed version
781 srcData = trimStorage.get();
782 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000783 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000784
reed@google.comac10a2d2010-12-22 21:39:39 +0000785 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000786 if (!this->npotRenderTargetSupport()) {
787 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
788 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
789 }
790
reed@google.comac10a2d2010-12-22 21:39:39 +0000791 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
792 glDesc.fAllocWidth);
793 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
794 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000795 } else if (!this->npotTextureSupport()) {
796 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
797 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000798 }
799
twiz@google.com0f31ca72011-03-18 17:38:11 +0000800 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
801 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
802 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000803 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000804 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
805 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000806 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000807 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
808 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000809 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000810 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
811 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000812 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000813
twiz@google.com0f31ca72011-03-18 17:38:11 +0000814 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000815 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000816 supports8BitPalette()) {
817 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
818 GrAssert(desc.fWidth == glDesc.fAllocWidth);
819 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000820 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000821 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000822 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000823 glDesc.fAllocWidth, glDesc.fAllocHeight,
824 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000825 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000826 } else {
827 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
828 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000829 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000830 glDesc.fAllocWidth, glDesc.fAllocHeight,
831 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000832 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000833 desc.fHeight, glDesc.fUploadFormat,
834 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000835 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000836
837 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
838 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
839 uint32_t maxTexels = extraW * extraH;
840 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
841 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
842
843 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
844
845 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
846 if (extraH) {
847 uint8_t* lastRowStart = (uint8_t*) srcData +
848 (desc.fHeight - 1) * rowSize;
849 uint8_t* extraRowStart = (uint8_t*)texels.get();
850
851 for (uint32_t i = 0; i < extraH; ++i) {
852 memcpy(extraRowStart, lastRowStart, rowSize);
853 extraRowStart += rowSize;
854 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000855 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000856 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
857 texels.get()));
858 }
859 if (extraW) {
860 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
861 uint8_t* extraTexel = (uint8_t*)texels.get();
862 for (uint32_t j = 0; j < desc.fHeight; ++j) {
863 for (uint32_t i = 0; i < extraW; ++i) {
864 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
865 extraTexel += glDesc.fUploadByteCount;
866 }
867 edgeTexel += rowSize;
868 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000869 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000870 desc.fHeight, glDesc.fUploadFormat,
871 glDesc.fUploadType, texels.get()));
872 }
873 if (extraW && extraH) {
874 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
875 - glDesc.fUploadByteCount;
876 uint8_t* extraTexel = (uint8_t*)texels.get();
877 for (uint32_t i = 0; i < extraW*extraH; ++i) {
878 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
879 extraTexel += glDesc.fUploadByteCount;
880 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000881 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000882 extraW, extraH, glDesc.fUploadFormat,
883 glDesc.fUploadType, texels.get()));
884 }
885
886 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000887 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000888 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
889 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000890 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000891 }
892 }
893
894 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
895
896 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
897 rtIDs.fStencilRenderbufferID = 0;
898 rtIDs.fMSColorRenderbufferID = 0;
899 rtIDs.fRTFBOID = 0;
900 rtIDs.fTexFBOID = 0;
901 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000902 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000903
904 if (renderTarget) {
905#if GR_COLLECT_STATS
906 ++fStats.fRenderTargetCreateCnt;
907#endif
908 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000909 GrGLenum status;
910 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000911
912 // If need have both RT flag and srcData we have
913 // to invert the data before uploading because FBO
914 // will be rendered bottom up
915 GrAssert(NULL == srcData);
916 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
917
twiz@google.com59a190b2011-03-14 21:23:01 +0000918 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000919 GrAssert(rtIDs.fTexFBOID);
920
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000921 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000922 // to one and then resolve to the texture bound to the other.
923 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000924 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000925 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000926 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000927 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
928 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000929 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000930 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000931 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
932 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000933 return return_null_texture();
934 }
935 } else {
936 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
937 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000938 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000939 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000940 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000941 }
942
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000943 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000944 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000945 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000946 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000947
twiz@google.com0f31ca72011-03-18 17:38:11 +0000948 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000949
950 const StencilFormat* stencilFormats = GrGLStencilFormats();
951 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000952 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000953 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000954 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000955 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000956 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000957 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000958 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000959 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000960 glDesc.fAllocWidth,
961 glDesc.fAllocHeight));
962 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000963 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000964 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000965 glDesc.fAllocWidth,
966 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000967 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000968 err = GrGLGetGLInterface()->fGetError();
969 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000970 continue;
971 }
972 }
973 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
974 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000975 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000976 rtIDs.fMSColorRenderbufferID));
977 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000978 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000979 samples,
980 msColorRenderbufferFormat,
981 glDesc.fAllocWidth,
982 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000983 err = GrGLGetGLInterface()->fGetError();
984 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000985 continue;
986 }
987 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000988 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000989
990#if GR_COLLECT_STATS
991 ++fStats.fRenderTargetChngCnt;
992#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000993 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
994 GR_GL_COLOR_ATTACHMENT0,
995 GR_GL_TEXTURE_2D,
996 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000997 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000998 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
999 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001000 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1001 status, desc.fWidth, desc.fHeight);
1002 continue;
1003 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001004 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001005 #if GR_COLLECT_STATS
1006 ++fStats.fRenderTargetChngCnt;
1007 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001008 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1009 GR_GL_COLOR_ATTACHMENT0,
1010 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001011 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001012
1013 }
1014 if (rtIDs.fStencilRenderbufferID) {
1015 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001016 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1017 GR_GL_STENCIL_ATTACHMENT,
1018 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001019 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001020 // if it is a packed format bind to depth also, otherwise
1021 // we may get an unsupported fbo completeness result
1022 if (stencilFormats[i].fPacked) {
1023 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1024 GR_GL_DEPTH_ATTACHMENT,
1025 GR_GL_RENDERBUFFER,
1026 rtIDs.fStencilRenderbufferID));
1027 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001028 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001029 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001030
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001031 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001032 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1033 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001034 // undo the depth bind
1035 if (rtIDs.fStencilRenderbufferID &&
1036 stencilFormats[i].fPacked) {
1037 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1038 GR_GL_DEPTH_ATTACHMENT,
1039 GR_GL_RENDERBUFFER,
1040 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001041 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001042 continue;
1043 }
1044 // we're successful!
1045 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001046 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001047 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001048 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001049 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001050 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001051 }
1052 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001053 break;
1054 }
1055 if (failed) {
1056 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001057 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001058 }
1059 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001060 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001061 }
1062 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001063 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001064 }
1065 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001066 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001067 }
1068 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1069 return return_null_texture();
1070 }
1071 }
1072#ifdef TRACE_TEXTURE_CREATION
1073 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1074 tex->fTextureID, width, height, tex->fUploadByteCount);
1075#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001076 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001077
1078 if (0 != rtIDs.fTexFBOID) {
1079 GrRenderTarget* rt = tex->asRenderTarget();
1080 // We've messed with FBO state but may not have set the correct viewport
1081 // so just dirty the rendertarget state to force a resend.
1082 fHWDrawState.fRenderTarget = NULL;
1083
1084 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001085 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001086 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1087 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001088 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001089 fCurrDrawState.fRenderTarget = rtSave;
1090 }
1091 }
1092 return tex;
1093}
1094
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001095GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001096 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 GR_GL(GenBuffers(1, &id));
1098 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001099 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001100 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001101 GrGLClearErr();
1102 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001103 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1104 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1105 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001106 GR_GL(DeleteBuffers(1, &id));
1107 // deleting bound buffer does implicit bind to 0
1108 fHWGeometryState.fVertexBuffer = NULL;
1109 return NULL;
1110 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001111 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001112 size, dynamic);
1113 fHWGeometryState.fVertexBuffer = vertexBuffer;
1114 return vertexBuffer;
1115 }
1116 return NULL;
1117}
1118
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001119GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001120 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001121 GR_GL(GenBuffers(1, &id));
1122 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001123 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001124 GrGLClearErr();
1125 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001126 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1127 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1128 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001129 GR_GL(DeleteBuffers(1, &id));
1130 // deleting bound buffer does implicit bind to 0
1131 fHWGeometryState.fIndexBuffer = NULL;
1132 return NULL;
1133 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001134 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001135 size, dynamic);
1136 fHWGeometryState.fIndexBuffer = indexBuffer;
1137 return indexBuffer;
1138 }
1139 return NULL;
1140}
1141
reed@google.comac10a2d2010-12-22 21:39:39 +00001142void GrGpuGL::flushScissor(const GrIRect* rect) {
1143 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001144 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001145 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001146
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001147 GrGLIRect scissor;
1148 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001149 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001150 rect->width(), rect->height());
1151 if (scissor.contains(vp)) {
1152 rect = NULL;
1153 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001154 }
1155
1156 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001157 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001158 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001159 fHWBounds.fScissorRect = scissor;
1160 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001161 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001162 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001163 fHWBounds.fScissorEnabled = true;
1164 }
1165 } else {
1166 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001167 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001168 fHWBounds.fScissorEnabled = false;
1169 }
1170 }
1171}
1172
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001173void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001174 if (NULL == fCurrDrawState.fRenderTarget) {
1175 return;
1176 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001177 GrIRect r;
1178 if (NULL != rect) {
1179 // flushScissor expects rect to be clipped to the target.
1180 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001181 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1182 fCurrDrawState.fRenderTarget->height());
1183 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001184 rect = &r;
1185 } else {
1186 return;
1187 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001188 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001189 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001190 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001191 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001192 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001193 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1194 GrColorUnpackG(color)/255.f,
1195 GrColorUnpackB(color)/255.f,
1196 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001197 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001198}
1199
bsalomon@google.com398109c2011-04-14 18:40:27 +00001200void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001201 if (NULL == fCurrDrawState.fRenderTarget) {
1202 return;
1203 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001204
1205 this->flushRenderTarget(&GrIRect::EmptyIRect());
1206
reed@google.comac10a2d2010-12-22 21:39:39 +00001207 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001208 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001209 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001210 }
1211 GR_GL(StencilMask(mask));
1212 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001213 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001214 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001215}
1216
bsalomon@google.com398109c2011-04-14 18:40:27 +00001217void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001218 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001219#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001220 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001221 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001222 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001223#else
1224 // we could just clear the clip bit but when we go through
1225 // angle a partial stencil mask will cause clears to be
1226 // turned into draws. Our contract on GrDrawTarget says that
1227 // changing the clip between stencil passes may or may not
1228 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001229 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001230#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001231 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001232 flushScissor(&rect);
1233 GR_GL(StencilMask(clipStencilMask));
1234 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001235 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001236 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001237}
1238
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001239void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001240 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001241}
1242
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001243bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1244 int left, int top, int width, int height,
1245 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001246 GrGLenum internalFormat; // we don't use this for glReadPixels
1247 GrGLenum format;
1248 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001249 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1250 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001251 }
1252 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1253 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1254 switch (tgt->getResolveType()) {
1255 case GrGLRenderTarget::kCantResolve_ResolveType:
1256 return false;
1257 case GrGLRenderTarget::kAutoResolves_ResolveType:
1258 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1259 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001260 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001261 break;
1262 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001263 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001264 // we don't track the state of the READ FBO ID.
1265 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1266 break;
1267 default:
1268 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001269 }
1270
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001271 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001272
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001273 // the read rect is viewport-relative
1274 GrGLIRect readRect;
1275 readRect.setRelativeTo(glvp, left, top, width, height);
1276 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001277 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001278 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001279
1280 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1281 // API presents top-to-bottom
1282 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001283 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001284 GrAutoMalloc rowStorage(stride);
1285 void* tmp = rowStorage.get();
1286
1287 const int halfY = height >> 1;
1288 char* top = reinterpret_cast<char*>(buffer);
1289 char* bottom = top + (height - 1) * stride;
1290 for (int y = 0; y < halfY; y++) {
1291 memcpy(tmp, top, stride);
1292 memcpy(top, bottom, stride);
1293 memcpy(bottom, tmp, stride);
1294 top += stride;
1295 bottom -= stride;
1296 }
1297 }
1298 return true;
1299}
1300
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001301void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001302
1303 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1304
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001305 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001306 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001307 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001308 #if GR_COLLECT_STATS
1309 ++fStats.fRenderTargetChngCnt;
1310 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001311 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001312 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1313 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001314 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1315 }
1316 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001317 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001318 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001319 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001320 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001321 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001322 fHWBounds.fViewportRect = vp;
1323 }
1324 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001325 if (NULL == bound || !bound->isEmpty()) {
1326 rt->flagAsNeedingResolve(bound);
1327 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001328}
1329
twiz@google.com0f31ca72011-03-18 17:38:11 +00001330GrGLenum gPrimitiveType2GLMode[] = {
1331 GR_GL_TRIANGLES,
1332 GR_GL_TRIANGLE_STRIP,
1333 GR_GL_TRIANGLE_FAN,
1334 GR_GL_POINTS,
1335 GR_GL_LINES,
1336 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001337};
1338
bsalomon@google.comd302f142011-03-03 13:54:13 +00001339#define SWAP_PER_DRAW 0
1340
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001341#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001342 #if GR_MAC_BUILD
1343 #include <AGL/agl.h>
1344 #elif GR_WIN32_BUILD
1345 void SwapBuf() {
1346 DWORD procID = GetCurrentProcessId();
1347 HWND hwnd = GetTopWindow(GetDesktopWindow());
1348 while(hwnd) {
1349 DWORD wndProcID = 0;
1350 GetWindowThreadProcessId(hwnd, &wndProcID);
1351 if(wndProcID == procID) {
1352 SwapBuffers(GetDC(hwnd));
1353 }
1354 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1355 }
1356 }
1357 #endif
1358#endif
1359
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001360void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1361 uint32_t startVertex,
1362 uint32_t startIndex,
1363 uint32_t vertexCount,
1364 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001365 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1366
twiz@google.com0f31ca72011-03-18 17:38:11 +00001367 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001368
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001369 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1370 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1371
1372 // our setupGeometry better have adjusted this to zero since
1373 // DrawElements always draws from the begining of the arrays for idx 0.
1374 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001375
1376 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001377 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001378#if SWAP_PER_DRAW
1379 glFlush();
1380 #if GR_MAC_BUILD
1381 aglSwapBuffers(aglGetCurrentContext());
1382 int set_a_break_pt_here = 9;
1383 aglSwapBuffers(aglGetCurrentContext());
1384 #elif GR_WIN32_BUILD
1385 SwapBuf();
1386 int set_a_break_pt_here = 9;
1387 SwapBuf();
1388 #endif
1389#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001390}
1391
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001392void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1393 uint32_t startVertex,
1394 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001395 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1396
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001397 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1398
1399 // our setupGeometry better have adjusted this to zero.
1400 // DrawElements doesn't take an offset so we always adjus the startVertex.
1401 GrAssert(0 == startVertex);
1402
1403 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1404 // account for startVertex in the DrawElements case. So we always
1405 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001406 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001407#if SWAP_PER_DRAW
1408 glFlush();
1409 #if GR_MAC_BUILD
1410 aglSwapBuffers(aglGetCurrentContext());
1411 int set_a_break_pt_here = 9;
1412 aglSwapBuffers(aglGetCurrentContext());
1413 #elif GR_WIN32_BUILD
1414 SwapBuf();
1415 int set_a_break_pt_here = 9;
1416 SwapBuf();
1417 #endif
1418#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001419}
1420
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001421void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001422
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001423 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001424 GrAssert(kNone_MSFBO != fMSFBOType);
1425 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001426 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001427 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001428 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001429 rt->textureFBOID()));
1430 #if GR_COLLECT_STATS
1431 ++fStats.fRenderTargetChngCnt;
1432 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001433 // make sure we go through flushRenderTarget() since we've modified
1434 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001435 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001436 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001437 const GrIRect dirtyRect = rt->getResolveRect();
1438 GrGLIRect r;
1439 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1440 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001441
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001442 if (kAppleES_MSFBO == fMSFBOType) {
1443 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001444 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001445 GR_GL(Scissor(r.fLeft, r.fBottom,
1446 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001447 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001448 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001449 fHWBounds.fScissorEnabled = true;
1450 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001451 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001452 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001453 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1454 flushScissor(NULL);
1455 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001456 int right = r.fLeft + r.fWidth;
1457 int top = r.fBottom + r.fHeight;
1458 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1459 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001460 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001461 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001462 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001463 }
1464}
1465
twiz@google.com0f31ca72011-03-18 17:38:11 +00001466static const GrGLenum grToGLStencilFunc[] = {
1467 GR_GL_ALWAYS, // kAlways_StencilFunc
1468 GR_GL_NEVER, // kNever_StencilFunc
1469 GR_GL_GREATER, // kGreater_StencilFunc
1470 GR_GL_GEQUAL, // kGEqual_StencilFunc
1471 GR_GL_LESS, // kLess_StencilFunc
1472 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1473 GR_GL_EQUAL, // kEqual_StencilFunc,
1474 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001475};
1476GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1477GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1478GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1479GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1480GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1481GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1482GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1483GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1484GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1485
twiz@google.com0f31ca72011-03-18 17:38:11 +00001486static const GrGLenum grToGLStencilOp[] = {
1487 GR_GL_KEEP, // kKeep_StencilOp
1488 GR_GL_REPLACE, // kReplace_StencilOp
1489 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1490 GR_GL_INCR, // kIncClamp_StencilOp
1491 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1492 GR_GL_DECR, // kDecClamp_StencilOp
1493 GR_GL_ZERO, // kZero_StencilOp
1494 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001495};
1496GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1497GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1498GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1499GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1500GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1501GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1502GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1503GR_STATIC_ASSERT(6 == kZero_StencilOp);
1504GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1505
reed@google.comac10a2d2010-12-22 21:39:39 +00001506void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001507 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001508
1509 // use stencil for clipping if clipping is enabled and the clip
1510 // has been written into the stencil.
1511 bool stencilClip = fClipState.fClipInStencil &&
1512 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001513 bool stencilChange = fHWStencilClip != stencilClip ||
1514 fHWDrawState.fStencilSettings != *settings ||
1515 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1516 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001517
1518 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001519
bsalomon@google.comd302f142011-03-03 13:54:13 +00001520 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1521 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001522
bsalomon@google.comd302f142011-03-03 13:54:13 +00001523 if (settings->isDisabled()) {
1524 if (stencilClip) {
1525 settings = &gClipStencilSettings;
1526 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001527 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001528
1529 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001530 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001531 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001532 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001533 #if GR_DEBUG
1534 if (!fStencilWrapOpsSupport) {
1535 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1536 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1537 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1538 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1539 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1540 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1541 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1542 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1543 }
1544 #endif
1545 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1546 GrAssert(stencilBits ||
1547 (GrStencilSettings::gDisabled ==
1548 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001549 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1550 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001551
1552 unsigned int frontRef = settings->fFrontFuncRef;
1553 unsigned int frontMask = settings->fFrontFuncMask;
1554 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001555 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001556
1557 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1558
1559 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1560 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1561 } else {
1562 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1563
1564 ConvertStencilFuncAndMask(settings->fFrontFunc,
1565 stencilClip,
1566 clipStencilMask,
1567 userStencilMask,
1568 &frontRef,
1569 &frontMask);
1570 frontWriteMask &= userStencilMask;
1571 }
1572 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001573 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001574 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001575 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001576 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001577 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001578 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001579 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001580 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001581 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001582
1583 unsigned int backRef = settings->fBackFuncRef;
1584 unsigned int backMask = settings->fBackFuncMask;
1585 unsigned int backWriteMask = settings->fBackWriteMask;
1586
1587
1588 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1589 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1590 backFunc = grToGLStencilFunc[settings->fBackFunc];
1591 } else {
1592 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1593 ConvertStencilFuncAndMask(settings->fBackFunc,
1594 stencilClip,
1595 clipStencilMask,
1596 userStencilMask,
1597 &backRef,
1598 &backMask);
1599 backWriteMask &= userStencilMask;
1600 }
1601
twiz@google.com0f31ca72011-03-18 17:38:11 +00001602 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1603 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1604 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1605 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1606 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001607 grToGLStencilOp[settings->fFrontPassOp],
1608 grToGLStencilOp[settings->fFrontPassOp]));
1609
twiz@google.com0f31ca72011-03-18 17:38:11 +00001610 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001611 grToGLStencilOp[settings->fBackPassOp],
1612 grToGLStencilOp[settings->fBackPassOp]));
1613 } else {
1614 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1615 GR_GL(StencilMask(frontWriteMask));
1616 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1617 grToGLStencilOp[settings->fFrontPassOp],
1618 grToGLStencilOp[settings->fFrontPassOp]));
1619 }
1620 }
1621 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001622 fHWStencilClip = stencilClip;
1623 }
1624}
1625
bsalomon@google.com0650e812011-04-08 18:07:53 +00001626bool GrGpuGL::useSmoothLines() {
1627 // there is a conflict between using smooth lines and our use of
1628 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1629 // but not in a premul-alpha way. So we only use them when our alpha
1630 // is 0xff.
1631
1632 // TODO: write a smarter line frag shader.
1633
1634 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1635 canDisableBlend();
1636}
1637
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001638void GrGpuGL::flushAAState(GrPrimitiveType type) {
1639 if (GR_GL_SUPPORT_DESKTOP) {
1640 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1641 // smooth lines.
1642
1643 // we prefer smooth lines over multisampled lines
1644 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001645 if (GrIsPrimTypeLines(type)) {
1646 bool smooth = useSmoothLines();
1647 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001648 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1649 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001650 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001651 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1652 fHWAAState.fSmoothLineEnabled = false;
1653 }
1654 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1655 fHWAAState.fMSAAEnabled) {
1656 GR_GL(Disable(GR_GL_MULTISAMPLE));
1657 fHWAAState.fMSAAEnabled = false;
1658 }
1659 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1660 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1661 fHWAAState.fMSAAEnabled) {
1662 if (fHWAAState.fMSAAEnabled) {
1663 GR_GL(Disable(GR_GL_MULTISAMPLE));
1664 fHWAAState.fMSAAEnabled = false;
1665 } else {
1666 GR_GL(Enable(GR_GL_MULTISAMPLE));
1667 fHWAAState.fMSAAEnabled = true;
1668 }
1669 }
1670 }
1671}
1672
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001673void GrGpuGL::flushBlend(GrPrimitiveType type,
1674 GrBlendCoeff srcCoeff,
1675 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001676 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1677 if (fHWBlendDisabled) {
1678 GR_GL(Enable(GR_GL_BLEND));
1679 fHWBlendDisabled = false;
1680 }
1681 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1682 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1683 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1684 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1685 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1686 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1687 }
1688 } else {
1689 bool blendOff = canDisableBlend();
1690 if (fHWBlendDisabled != blendOff) {
1691 if (blendOff) {
1692 GR_GL(Disable(GR_GL_BLEND));
1693 } else {
1694 GR_GL(Enable(GR_GL_BLEND));
1695 }
1696 fHWBlendDisabled = blendOff;
1697 }
1698 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001699 if (fHWDrawState.fSrcBlend != srcCoeff ||
1700 fHWDrawState.fDstBlend != dstCoeff) {
1701 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1702 gXfermodeCoeff2Blend[dstCoeff]));
1703 fHWDrawState.fSrcBlend = srcCoeff;
1704 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001705 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001706 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1707 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001708 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1709
1710 float c[] = {
1711 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1712 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1713 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1714 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1715 };
1716 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1717 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1718 }
1719 }
1720 }
1721}
1722
bsalomon@google.comffca4002011-02-22 20:34:01 +00001723bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001724
1725 // GrGpu::setupClipAndFlushState should have already checked this
1726 // and bailed if not true.
1727 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001728
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001729 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001730 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001731 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001732 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001733
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001734 // true for now, but maybe not with GrEffect.
1735 GrAssert(NULL != nextTexture);
1736 // if we created a rt/tex and rendered to it without using a
1737 // texture and now we're texuring from the rt it will still be
1738 // the last bound texture, but it needs resolving. So keep this
1739 // out of the "last != next" check.
1740 GrGLRenderTarget* texRT =
1741 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1742 if (NULL != texRT) {
1743 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001744 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001745
1746 if (fHWDrawState.fTextures[s] != nextTexture) {
1747 setTextureUnit(s);
1748 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1749 #if GR_COLLECT_STATS
1750 ++fStats.fTextureChngCnt;
1751 #endif
1752 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1753 fHWDrawState.fTextures[s] = nextTexture;
1754 }
1755
1756 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1757 const GrGLTexture::TexParams& oldTexParams =
1758 nextTexture->getTexParams();
1759 GrGLTexture::TexParams newTexParams;
1760
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001761 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1762 newTexParams.fFilter = GR_GL_NEAREST;
1763 } else {
1764 newTexParams.fFilter = GR_GL_LINEAR;
1765 }
1766
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001767 newTexParams.fWrapS =
1768 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1769 newTexParams.fWrapT =
1770 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1771
1772 if (newTexParams.fFilter != oldTexParams.fFilter) {
1773 setTextureUnit(s);
1774 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1775 GR_GL_TEXTURE_MAG_FILTER,
1776 newTexParams.fFilter));
1777 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1778 GR_GL_TEXTURE_MIN_FILTER,
1779 newTexParams.fFilter));
1780 }
1781 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1782 setTextureUnit(s);
1783 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1784 GR_GL_TEXTURE_WRAP_S,
1785 newTexParams.fWrapS));
1786 }
1787 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1788 setTextureUnit(s);
1789 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1790 GR_GL_TEXTURE_WRAP_T,
1791 newTexParams.fWrapT));
1792 }
1793 nextTexture->setTexParams(newTexParams);
1794
1795 // The texture matrix has to compensate for texture width/height
1796 // and NPOT-embedded-in-POT
1797 fDirtyFlags.fTextureChangedMask |= (1 << s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001798 }
1799 }
1800
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001801 GrIRect* rect = NULL;
1802 GrIRect clipBounds;
1803 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1804 fClip.hasConservativeBounds()) {
1805 fClip.getConservativeBounds().roundOut(&clipBounds);
1806 rect = &clipBounds;
1807 }
1808 this->flushRenderTarget(rect);
1809 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001810
reed@google.comac10a2d2010-12-22 21:39:39 +00001811 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1812 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1813 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001814 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001815 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001816 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001817 }
1818 }
1819
bsalomon@google.comd302f142011-03-03 13:54:13 +00001820 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1821 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001822 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001823 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001824 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001825 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001826 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001827 }
1828 GR_GL(ColorMask(mask, mask, mask, mask));
1829 }
1830
bsalomon@google.comd302f142011-03-03 13:54:13 +00001831 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1832 switch (fCurrDrawState.fDrawFace) {
1833 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001834 GR_GL(Enable(GR_GL_CULL_FACE));
1835 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001836 break;
1837 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001838 GR_GL(Enable(GR_GL_CULL_FACE));
1839 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001840 break;
1841 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001842 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001843 break;
1844 default:
1845 GrCrash("Unknown draw face.");
1846 }
1847 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1848 }
1849
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001850#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001851 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001852 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001853 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001854 NULL == fCurrDrawState.fRenderTarget ||
1855 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001856 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001857 fCurrDrawState.fRenderTarget);
1858 }
1859#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001860
reed@google.comac10a2d2010-12-22 21:39:39 +00001861 flushStencil();
1862
bsalomon@google.comd302f142011-03-03 13:54:13 +00001863 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001864 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001865 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001866}
1867
1868void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001869 if (fHWGeometryState.fVertexBuffer != buffer) {
1870 fHWGeometryState.fArrayPtrsDirty = true;
1871 fHWGeometryState.fVertexBuffer = buffer;
1872 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001873}
1874
1875void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001876 if (fHWGeometryState.fVertexBuffer == buffer) {
1877 // deleting bound buffer does implied bind to 0
1878 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001879 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001880 }
1881}
1882
1883void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1884 fGeometrySrc.fIndexBuffer = buffer;
1885}
1886
1887void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001888 if (fHWGeometryState.fIndexBuffer == buffer) {
1889 // deleting bound buffer does implied bind to 0
1890 fHWGeometryState.fIndexBuffer = NULL;
1891 }
1892}
1893
reed@google.comac10a2d2010-12-22 21:39:39 +00001894void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1895 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001896 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001897 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001898 }
1899 if (fHWDrawState.fRenderTarget == renderTarget) {
1900 fHWDrawState.fRenderTarget = NULL;
1901 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001902}
1903
1904void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001905 for (int s = 0; s < kNumStages; ++s) {
1906 if (fCurrDrawState.fTextures[s] == texture) {
1907 fCurrDrawState.fTextures[s] = NULL;
1908 }
1909 if (fHWDrawState.fTextures[s] == texture) {
1910 // deleting bound texture does implied bind to 0
1911 fHWDrawState.fTextures[s] = NULL;
1912 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001913 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001914}
1915
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001916bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001917 GrGLenum* internalFormat,
1918 GrGLenum* format,
1919 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001920 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001921 case kRGBA_8888_GrPixelConfig:
1922 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001923 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001924 if (GR_GL_SUPPORT_ES) {
1925 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1926 // format for a BGRA is BGRA not RGBA (as on desktop)
1927 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1928 } else {
1929 *internalFormat = GR_GL_RGBA;
1930 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001931 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001932 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001933 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001934 *format = GR_GL_RGB;
1935 *internalFormat = GR_GL_RGB;
1936 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001937 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001938 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001939 *format = GR_GL_RGBA;
1940 *internalFormat = GR_GL_RGBA;
1941 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001942 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001943 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001944 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001945 *format = GR_GL_PALETTE8_RGBA8;
1946 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001947 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001948 } else {
1949 return false;
1950 }
1951 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001952 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001953 *format = GR_GL_ALPHA;
1954 *internalFormat = GR_GL_ALPHA;
1955 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001956 break;
1957 default:
1958 return false;
1959 }
1960 return true;
1961}
1962
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001963void GrGpuGL::setTextureUnit(int unit) {
1964 GrAssert(unit >= 0 && unit < kNumStages);
1965 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001966 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001967 fActiveTextureUnitIdx = unit;
1968 }
1969}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001970
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001971void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001972 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1973 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001974 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1975 }
1976}
1977
reed@google.comac10a2d2010-12-22 21:39:39 +00001978/* On ES the internalFormat and format must match for TexImage and we use
1979 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1980 decide the internalFormat. However, on ES internalFormat for
1981 RenderBufferStorage* has to be a specific format (not a base format like
1982 GL_RGBA).
1983 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001984bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001985 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001986 case kRGBA_8888_GrPixelConfig:
1987 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001988 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001989 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001990 return true;
1991 } else {
1992 return false;
1993 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001994 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001995 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1996 // with FBO extension desktop GL has
1997 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001998 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001999 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002000 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002001 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002002 return true;
2003 default:
2004 return false;
2005 }
2006}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002007
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002008void GrGpuGL::resetDirtyFlags() {
2009 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2010}
2011
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002012void GrGpuGL::setBuffers(bool indexed,
2013 int* extraVertexOffset,
2014 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002015
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002016 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002017
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002018 GrGLVertexBuffer* vbuf;
2019 switch (fGeometrySrc.fVertexSrc) {
2020 case kBuffer_GeometrySrcType:
2021 *extraVertexOffset = 0;
2022 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2023 break;
2024 case kArray_GeometrySrcType:
2025 case kReserved_GeometrySrcType:
2026 finalizeReservedVertices();
2027 *extraVertexOffset = fCurrPoolStartVertex;
2028 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2029 break;
2030 default:
2031 vbuf = NULL; // suppress warning
2032 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002033 }
2034
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002035 GrAssert(NULL != vbuf);
2036 GrAssert(!vbuf->isLocked());
2037 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002038 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002039 fHWGeometryState.fArrayPtrsDirty = true;
2040 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002041 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002042
2043 if (indexed) {
2044 GrAssert(NULL != extraIndexOffset);
2045
2046 GrGLIndexBuffer* ibuf;
2047 switch (fGeometrySrc.fIndexSrc) {
2048 case kBuffer_GeometrySrcType:
2049 *extraIndexOffset = 0;
2050 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2051 break;
2052 case kArray_GeometrySrcType:
2053 case kReserved_GeometrySrcType:
2054 finalizeReservedIndices();
2055 *extraIndexOffset = fCurrPoolStartIndex;
2056 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2057 break;
2058 default:
2059 ibuf = NULL; // suppress warning
2060 GrCrash("Unknown geometry src type!");
2061 }
2062
2063 GrAssert(NULL != ibuf);
2064 GrAssert(!ibuf->isLocked());
2065 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002066 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002067 fHWGeometryState.fIndexBuffer = ibuf;
2068 }
2069 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002070}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002071
2072int GrGpuGL::getMaxEdges() const {
2073 // FIXME: This is a pessimistic estimate based on how many other things
2074 // want to add uniforms. This should be centralized somewhere.
2075 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2076}