blob: 2d7d512c5e1965554058e45901d0642e2f3374e1 [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.com91958362011-06-13 17:58:13 +0000442 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
443 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
444 // Our render targets are always created with textures as the color
445 // attachment, hence this min:
446 fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000447
reed@google.comac10a2d2010-12-22 21:39:39 +0000448 /* The iPhone 4 has a restriction that for an FBO with texture color
449 attachment with height <= 8 then the width must be <= height. Here
450 we look for such a limitation.
451 */
reed@google.comeeeb5a02010-12-23 15:12:59 +0000452 if (gPrintStartupSpew) {
453 GrPrintf("Small height FBO texture experiments\n");
454 }
bsalomon@google.com91958362011-06-13 17:58:13 +0000455 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000456 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
bsalomon@google.com91958362011-06-13 17:58:13 +0000457 GrGLuint w = fMaxRenderTargetSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000458 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000459 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000460 if (gPrintStartupSpew) {
461 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
462 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000463 fMinRenderTargetHeight = i;
464 break;
465 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000466 if (gPrintStartupSpew) {
467 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
468 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000469 }
470 }
471 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
472
reed@google.comeeeb5a02010-12-23 15:12:59 +0000473 if (gPrintStartupSpew) {
474 GrPrintf("Small width FBO texture experiments\n");
475 }
bsalomon@google.com91958362011-06-13 17:58:13 +0000476 fMinRenderTargetWidth = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000477 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
478 GrGLuint w = i;
bsalomon@google.com91958362011-06-13 17:58:13 +0000479 GrGLuint h = fMaxRenderTargetSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000480 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000481 if (gPrintStartupSpew) {
482 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
483 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000484 fMinRenderTargetWidth = i;
485 break;
486 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000487 if (gPrintStartupSpew) {
488 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
489 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000490 }
491 }
492 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
reed@google.comac10a2d2010-12-22 21:39:39 +0000493}
494
495GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000496}
497
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000498void GrGpuGL::resetContext() {
499 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000500 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000501 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000502
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000503 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000504 GR_GL(Disable(GR_GL_DEPTH_TEST));
505 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000506
twiz@google.com0f31ca72011-03-18 17:38:11 +0000507 GR_GL(Disable(GR_GL_CULL_FACE));
508 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000509 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000510
twiz@google.com0f31ca72011-03-18 17:38:11 +0000511 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000512 if (GR_GL_SUPPORT_DESKTOP) {
513 GR_GL(Disable(GR_GL_LINE_SMOOTH));
514 GR_GL(Disable(GR_GL_POINT_SMOOTH));
515 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000516 fHWAAState.fMSAAEnabled = false;
517 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000518 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000519
twiz@google.com0f31ca72011-03-18 17:38:11 +0000520 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000521 fHWDrawState.fFlagBits = 0;
522
reed@google.comac10a2d2010-12-22 21:39:39 +0000523 // we only ever use lines in hairline mode
524 GR_GL(LineWidth(1));
525
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000526 // invalid
527 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000528
reed@google.comac10a2d2010-12-22 21:39:39 +0000529 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000530 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
531 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000532
533 fHWDrawState.fBlendConstant = 0x00000000;
534 GR_GL(BlendColor(0,0,0,0));
535
reed@google.comac10a2d2010-12-22 21:39:39 +0000536 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000537
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000538 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000539
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000540 for (int s = 0; s < kNumStages; ++s) {
541 fHWDrawState.fTextures[s] = NULL;
542 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
543 -GR_ScalarMax,
544 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000545
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000546 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000547 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000548
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000549 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000550 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000551 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000552 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000553
bsalomon@google.comd302f142011-03-03 13:54:13 +0000554 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000555 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000556 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000557
558 fHWGeometryState.fIndexBuffer = NULL;
559 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000560
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000561 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000562
twiz@google.com0f31ca72011-03-18 17:38:11 +0000563 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000564 fHWDrawState.fRenderTarget = NULL;
565}
566
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000567GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
568
569 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
570 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
571 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
572 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
573
574 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
575 if (isRenderTarget) {
576 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
577 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
578 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
579 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
580 } else {
581 GrAssert(!isTexture); // this should have been filtered by GrContext
582 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
583 }
584 } else {
585 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
586 }
587 // we don't know what the RB ids are without glGets and we don't care
588 // since we aren't responsible for deleting them.
589 rtIDs.fStencilRenderbufferID = 0;
590 rtIDs.fMSColorRenderbufferID = 0;
591
592 rtIDs.fOwnIDs = false;
593 } else {
594 rtIDs.reset();
595 }
596
597 if (isTexture) {
598 GrGLTexture::GLTextureDesc texDesc;
599 GrGLenum dontCare;
600 if (!canBeTexture(desc.fConfig, &dontCare,
601 &texDesc.fUploadFormat,
602 &texDesc.fUploadType)) {
603 return NULL;
604 }
605
606 GrGLTexture::TexParams params;
607
608 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
609 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
610
611 texDesc.fFormat = texDesc.fFormat;
612 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
613 texDesc.fStencilBits = desc.fStencilBits;
614 texDesc.fTextureID = desc.fPlatformTexture;
615 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
616 texDesc.fOwnsID = false;
617
618 params.invalidate(); // rather than do glGets.
619
620 return new GrGLTexture(this, texDesc, rtIDs, params);
621 } else {
622 GrGLIRect viewport;
623 viewport.fLeft = 0;
624 viewport.fBottom = 0;
625 viewport.fWidth = desc.fWidth;
626 viewport.fHeight = desc.fHeight;
627
628 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
629 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
630 viewport, NULL);
631 }
632}
633
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000634GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000635
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000636 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000637
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000638 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000639 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
640 rtIDs.fMSColorRenderbufferID = 0;
641 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000642
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000643 GrGLIRect viewport;
644 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000645 GrGLuint stencilBits;
646 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000647
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000648 GrGLint samples;
649 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
650
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000651 rtIDs.fOwnIDs = false;
652
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000653 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
654 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000655}
656
bsalomon@google.com5782d712011-01-21 21:03:59 +0000657///////////////////////////////////////////////////////////////////////////////
658
twiz@google.com0f31ca72011-03-18 17:38:11 +0000659static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000660
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000661struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000662 GrGLenum fEnum;
663 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000664 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000665};
666
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000667const StencilFormat* GrGLStencilFormats() {
668 // defines stencil formats from more to less preferred
669 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000670 {GR_GL_STENCIL_INDEX8, 8, false},
671 {GR_GL_STENCIL_INDEX16, 16, false},
672 {GR_GL_DEPTH24_STENCIL8, 8, true },
673 {GR_GL_STENCIL_INDEX4, 4, false},
674 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
675 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
676 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000677 };
678
679 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000680 {GR_GL_STENCIL_INDEX8, 8, false},
681 {GR_GL_DEPTH24_STENCIL8, 8, true },
682 {GR_GL_STENCIL_INDEX4, 4, false},
683 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000684 };
685
686 if (GR_GL_SUPPORT_DESKTOP) {
687 return desktopStencilFormats;
688 } else {
689 return esStencilFormats;
690 }
691}
692
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000693// good to set a break-point here to know when createTexture fails
694static GrTexture* return_null_texture() {
695// GrAssert(!"null texture");
696 return NULL;
697}
698
699#if GR_DEBUG
700static size_t as_size_t(int x) {
701 return x;
702}
703#endif
704
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000705GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000706 const void* srcData,
707 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000708
709#if GR_COLLECT_STATS
710 ++fStats.fTextureCreateCnt;
711#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000712
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000713 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000714
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000715 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000716 GR_GL_NEAREST,
717 GR_GL_CLAMP_TO_EDGE,
718 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000719 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000720
reed@google.comac10a2d2010-12-22 21:39:39 +0000721 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000722 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000723
724 glDesc.fContentWidth = desc.fWidth;
725 glDesc.fContentHeight = desc.fHeight;
726 glDesc.fAllocWidth = desc.fWidth;
727 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000728 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000729 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000730 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000731
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000732 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000733 if (!canBeTexture(desc.fFormat,
734 &internalFormat,
735 &glDesc.fUploadFormat,
736 &glDesc.fUploadType)) {
737 return return_null_texture();
738 }
739
740 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000741 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000742 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000743 GrPrintf("AA RT requested but not supported on this platform.");
744 }
745
746 GR_GL(GenTextures(1, &glDesc.fTextureID));
747 if (!glDesc.fTextureID) {
748 return return_null_texture();
749 }
750
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000751 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000752
reed@google.com5e762232011-04-04 18:15:49 +0000753 // in case we need a temporary, trimmed copy of the src pixels
754 GrAutoSMalloc<128 * 128> trimStorage;
755
reed@google.comac10a2d2010-12-22 21:39:39 +0000756 /*
757 * check if our srcData has extra bytes past each row. If so, we need
758 * to trim those off here, since GL doesn't let us pass the rowBytes as
759 * a parameter to glTexImage2D
760 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000761 if (GR_GL_SUPPORT_DESKTOP) {
762 if (srcData) {
763 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
764 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000765 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000766 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000767 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
768 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000769 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000770 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000771 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000772 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000773 for (uint32_t y = 0; y < desc.fHeight; y++) {
774 memcpy(dst, src, trimRowBytes);
775 src += rowBytes;
776 dst += trimRowBytes;
777 }
778 // now point srcData to our trimmed version
779 srcData = trimStorage.get();
780 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000781 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000782
reed@google.comac10a2d2010-12-22 21:39:39 +0000783 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000784 if (!this->npotRenderTargetSupport()) {
785 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
786 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
787 }
788
reed@google.comac10a2d2010-12-22 21:39:39 +0000789 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
790 glDesc.fAllocWidth);
791 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
792 glDesc.fAllocHeight);
bsalomon@google.com91958362011-06-13 17:58:13 +0000793 if ((int)glDesc.fAllocWidth > fMaxRenderTargetSize ||
794 (int)glDesc.fAllocHeight > fMaxRenderTargetSize) {
795 return return_null_texture();
796 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000797 } else if (!this->npotTextureSupport()) {
798 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
799 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
bsalomon@google.com91958362011-06-13 17:58:13 +0000800 if ((int)glDesc.fAllocWidth > fMaxTextureSize ||
801 (int)glDesc.fAllocHeight > fMaxTextureSize) {
802 return return_null_texture();
803 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000804 }
805
twiz@google.com0f31ca72011-03-18 17:38:11 +0000806 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
807 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
808 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000809 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000810 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
811 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000812 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000813 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
814 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000815 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000816 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
817 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000818 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000819
twiz@google.com0f31ca72011-03-18 17:38:11 +0000820 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000821 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000822 supports8BitPalette()) {
823 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
824 GrAssert(desc.fWidth == glDesc.fAllocWidth);
825 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000826 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000827 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000828 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000829 glDesc.fAllocWidth, glDesc.fAllocHeight,
830 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000831 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000832 } else {
833 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
834 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000835 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000836 glDesc.fAllocWidth, glDesc.fAllocHeight,
837 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000838 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000839 desc.fHeight, glDesc.fUploadFormat,
840 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000841 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000842
843 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
844 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
845 uint32_t maxTexels = extraW * extraH;
846 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
847 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
848
849 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
850
851 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
852 if (extraH) {
853 uint8_t* lastRowStart = (uint8_t*) srcData +
854 (desc.fHeight - 1) * rowSize;
855 uint8_t* extraRowStart = (uint8_t*)texels.get();
856
857 for (uint32_t i = 0; i < extraH; ++i) {
858 memcpy(extraRowStart, lastRowStart, rowSize);
859 extraRowStart += rowSize;
860 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000861 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000862 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
863 texels.get()));
864 }
865 if (extraW) {
866 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
867 uint8_t* extraTexel = (uint8_t*)texels.get();
868 for (uint32_t j = 0; j < desc.fHeight; ++j) {
869 for (uint32_t i = 0; i < extraW; ++i) {
870 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
871 extraTexel += glDesc.fUploadByteCount;
872 }
873 edgeTexel += rowSize;
874 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000875 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000876 desc.fHeight, glDesc.fUploadFormat,
877 glDesc.fUploadType, texels.get()));
878 }
879 if (extraW && extraH) {
880 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
881 - glDesc.fUploadByteCount;
882 uint8_t* extraTexel = (uint8_t*)texels.get();
883 for (uint32_t i = 0; i < extraW*extraH; ++i) {
884 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
885 extraTexel += glDesc.fUploadByteCount;
886 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000887 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000888 extraW, extraH, glDesc.fUploadFormat,
889 glDesc.fUploadType, texels.get()));
890 }
891
892 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000893 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000894 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
895 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000896 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000897 }
898 }
899
900 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
901
902 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
903 rtIDs.fStencilRenderbufferID = 0;
904 rtIDs.fMSColorRenderbufferID = 0;
905 rtIDs.fRTFBOID = 0;
906 rtIDs.fTexFBOID = 0;
907 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000908 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000909
910 if (renderTarget) {
911#if GR_COLLECT_STATS
912 ++fStats.fRenderTargetCreateCnt;
913#endif
914 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000915 GrGLenum status;
916 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000917
918 // If need have both RT flag and srcData we have
919 // to invert the data before uploading because FBO
920 // will be rendered bottom up
921 GrAssert(NULL == srcData);
922 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
923
twiz@google.com59a190b2011-03-14 21:23:01 +0000924 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000925 GrAssert(rtIDs.fTexFBOID);
926
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000927 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000928 // to one and then resolve to the texture bound to the other.
929 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000930 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000931 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000932 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000933 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
934 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000935 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000936 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000937 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
938 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000939 return return_null_texture();
940 }
941 } else {
942 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
943 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000944 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000945 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000946 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000947 }
948
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000949 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000950 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000951 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000952 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000953
twiz@google.com0f31ca72011-03-18 17:38:11 +0000954 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000955
956 const StencilFormat* stencilFormats = GrGLStencilFormats();
957 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000958 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000959 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000960 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000961 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000962 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000963 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000964 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000965 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000966 glDesc.fAllocWidth,
967 glDesc.fAllocHeight));
968 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000969 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000970 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000971 glDesc.fAllocWidth,
972 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000973 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000974 err = GrGLGetGLInterface()->fGetError();
975 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000976 continue;
977 }
978 }
979 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
980 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000981 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000982 rtIDs.fMSColorRenderbufferID));
983 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000984 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000985 samples,
986 msColorRenderbufferFormat,
987 glDesc.fAllocWidth,
988 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000989 err = GrGLGetGLInterface()->fGetError();
990 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000991 continue;
992 }
993 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000994 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000995
996#if GR_COLLECT_STATS
997 ++fStats.fRenderTargetChngCnt;
998#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000999 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1000 GR_GL_COLOR_ATTACHMENT0,
1001 GR_GL_TEXTURE_2D,
1002 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001003 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001004 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1005 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001006 continue;
1007 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001008 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001009 #if GR_COLLECT_STATS
1010 ++fStats.fRenderTargetChngCnt;
1011 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001012 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1013 GR_GL_COLOR_ATTACHMENT0,
1014 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001015 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001016
1017 }
1018 if (rtIDs.fStencilRenderbufferID) {
1019 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001020 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1021 GR_GL_STENCIL_ATTACHMENT,
1022 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001023 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001024 // if it is a packed format bind to depth also, otherwise
1025 // we may get an unsupported fbo completeness result
1026 if (stencilFormats[i].fPacked) {
1027 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1028 GR_GL_DEPTH_ATTACHMENT,
1029 GR_GL_RENDERBUFFER,
1030 rtIDs.fStencilRenderbufferID));
1031 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001032 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001033 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001034
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001035 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
bsalomon@google.com9283b582011-04-08 19:00:04 +00001036 // undo the depth bind
1037 if (rtIDs.fStencilRenderbufferID &&
1038 stencilFormats[i].fPacked) {
1039 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1040 GR_GL_DEPTH_ATTACHMENT,
1041 GR_GL_RENDERBUFFER,
1042 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001043 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001044 continue;
1045 }
1046 // we're successful!
1047 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001048 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001049 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001050 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001051 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001052 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001053 }
1054 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001055 break;
1056 }
1057 if (failed) {
1058 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001059 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001060 }
1061 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001062 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001063 }
1064 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001065 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001066 }
1067 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001068 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001069 }
1070 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1071 return return_null_texture();
1072 }
1073 }
1074#ifdef TRACE_TEXTURE_CREATION
1075 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1076 tex->fTextureID, width, height, tex->fUploadByteCount);
1077#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001078 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001079
1080 if (0 != rtIDs.fTexFBOID) {
1081 GrRenderTarget* rt = tex->asRenderTarget();
1082 // We've messed with FBO state but may not have set the correct viewport
1083 // so just dirty the rendertarget state to force a resend.
1084 fHWDrawState.fRenderTarget = NULL;
1085
1086 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001087 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1089 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001090 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001091 fCurrDrawState.fRenderTarget = rtSave;
1092 }
1093 }
1094 return tex;
1095}
1096
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001097GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001098 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001099 GR_GL(GenBuffers(1, &id));
1100 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001101 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001102 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001103 GrGLClearErr();
1104 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001105 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1106 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1107 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001108 GR_GL(DeleteBuffers(1, &id));
1109 // deleting bound buffer does implicit bind to 0
1110 fHWGeometryState.fVertexBuffer = NULL;
1111 return NULL;
1112 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001113 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001114 size, dynamic);
1115 fHWGeometryState.fVertexBuffer = vertexBuffer;
1116 return vertexBuffer;
1117 }
1118 return NULL;
1119}
1120
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001121GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001122 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001123 GR_GL(GenBuffers(1, &id));
1124 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001125 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001126 GrGLClearErr();
1127 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001128 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1129 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1130 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001131 GR_GL(DeleteBuffers(1, &id));
1132 // deleting bound buffer does implicit bind to 0
1133 fHWGeometryState.fIndexBuffer = NULL;
1134 return NULL;
1135 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001136 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001137 size, dynamic);
1138 fHWGeometryState.fIndexBuffer = indexBuffer;
1139 return indexBuffer;
1140 }
1141 return NULL;
1142}
1143
reed@google.comac10a2d2010-12-22 21:39:39 +00001144void GrGpuGL::flushScissor(const GrIRect* rect) {
1145 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001146 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001147 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001148
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001149 GrGLIRect scissor;
1150 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001151 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001152 rect->width(), rect->height());
1153 if (scissor.contains(vp)) {
1154 rect = NULL;
1155 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001156 }
1157
1158 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001159 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001160 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001161 fHWBounds.fScissorRect = scissor;
1162 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001163 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001164 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001165 fHWBounds.fScissorEnabled = true;
1166 }
1167 } else {
1168 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001169 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001170 fHWBounds.fScissorEnabled = false;
1171 }
1172 }
1173}
1174
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001175void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001176 if (NULL == fCurrDrawState.fRenderTarget) {
1177 return;
1178 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001179 GrIRect r;
1180 if (NULL != rect) {
1181 // flushScissor expects rect to be clipped to the target.
1182 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001183 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1184 fCurrDrawState.fRenderTarget->height());
1185 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001186 rect = &r;
1187 } else {
1188 return;
1189 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001190 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001191 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001192 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001193 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001194 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001195 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1196 GrColorUnpackG(color)/255.f,
1197 GrColorUnpackB(color)/255.f,
1198 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001199 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001200}
1201
bsalomon@google.com398109c2011-04-14 18:40:27 +00001202void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001203 if (NULL == fCurrDrawState.fRenderTarget) {
1204 return;
1205 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001206
1207 this->flushRenderTarget(&GrIRect::EmptyIRect());
1208
reed@google.comac10a2d2010-12-22 21:39:39 +00001209 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001210 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001211 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001212 }
1213 GR_GL(StencilMask(mask));
1214 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001215 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001216 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001217}
1218
bsalomon@google.com398109c2011-04-14 18:40:27 +00001219void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001220 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001221#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001222 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001223 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001224 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001225#else
1226 // we could just clear the clip bit but when we go through
1227 // angle a partial stencil mask will cause clears to be
1228 // turned into draws. Our contract on GrDrawTarget says that
1229 // changing the clip between stencil passes may or may not
1230 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001231 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001232#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001233 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001234 flushScissor(&rect);
1235 GR_GL(StencilMask(clipStencilMask));
1236 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001237 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001238 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001239}
1240
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001241void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001242 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001243}
1244
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001245bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1246 int left, int top, int width, int height,
1247 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001248 GrGLenum internalFormat; // we don't use this for glReadPixels
1249 GrGLenum format;
1250 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001251 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1252 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001253 }
1254 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1255 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1256 switch (tgt->getResolveType()) {
1257 case GrGLRenderTarget::kCantResolve_ResolveType:
1258 return false;
1259 case GrGLRenderTarget::kAutoResolves_ResolveType:
1260 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1261 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001262 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001263 break;
1264 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001265 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001266 // we don't track the state of the READ FBO ID.
1267 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1268 break;
1269 default:
1270 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001271 }
1272
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001273 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001274
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001275 // the read rect is viewport-relative
1276 GrGLIRect readRect;
1277 readRect.setRelativeTo(glvp, left, top, width, height);
1278 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001279 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001280 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001281
1282 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1283 // API presents top-to-bottom
1284 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001285 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001286 GrAutoMalloc rowStorage(stride);
1287 void* tmp = rowStorage.get();
1288
1289 const int halfY = height >> 1;
1290 char* top = reinterpret_cast<char*>(buffer);
1291 char* bottom = top + (height - 1) * stride;
1292 for (int y = 0; y < halfY; y++) {
1293 memcpy(tmp, top, stride);
1294 memcpy(top, bottom, stride);
1295 memcpy(bottom, tmp, stride);
1296 top += stride;
1297 bottom -= stride;
1298 }
1299 }
1300 return true;
1301}
1302
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001303void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001304
1305 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1306
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001307 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001308 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001309 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001310 #if GR_COLLECT_STATS
1311 ++fStats.fRenderTargetChngCnt;
1312 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001313 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001314 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1315 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comb9255d52011-06-13 18:54:59 +00001316 GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
reed@google.comac10a2d2010-12-22 21:39:39 +00001317 }
1318 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001319 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001320 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001321 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001322 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001323 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001324 fHWBounds.fViewportRect = vp;
1325 }
1326 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001327 if (NULL == bound || !bound->isEmpty()) {
1328 rt->flagAsNeedingResolve(bound);
1329 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001330}
1331
twiz@google.com0f31ca72011-03-18 17:38:11 +00001332GrGLenum gPrimitiveType2GLMode[] = {
1333 GR_GL_TRIANGLES,
1334 GR_GL_TRIANGLE_STRIP,
1335 GR_GL_TRIANGLE_FAN,
1336 GR_GL_POINTS,
1337 GR_GL_LINES,
1338 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001339};
1340
bsalomon@google.comd302f142011-03-03 13:54:13 +00001341#define SWAP_PER_DRAW 0
1342
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001343#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001344 #if GR_MAC_BUILD
1345 #include <AGL/agl.h>
1346 #elif GR_WIN32_BUILD
1347 void SwapBuf() {
1348 DWORD procID = GetCurrentProcessId();
1349 HWND hwnd = GetTopWindow(GetDesktopWindow());
1350 while(hwnd) {
1351 DWORD wndProcID = 0;
1352 GetWindowThreadProcessId(hwnd, &wndProcID);
1353 if(wndProcID == procID) {
1354 SwapBuffers(GetDC(hwnd));
1355 }
1356 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1357 }
1358 }
1359 #endif
1360#endif
1361
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001362void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1363 uint32_t startVertex,
1364 uint32_t startIndex,
1365 uint32_t vertexCount,
1366 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001367 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1368
twiz@google.com0f31ca72011-03-18 17:38:11 +00001369 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001370
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001371 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1372 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1373
1374 // our setupGeometry better have adjusted this to zero since
1375 // DrawElements always draws from the begining of the arrays for idx 0.
1376 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001377
1378 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001379 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001380#if SWAP_PER_DRAW
1381 glFlush();
1382 #if GR_MAC_BUILD
1383 aglSwapBuffers(aglGetCurrentContext());
1384 int set_a_break_pt_here = 9;
1385 aglSwapBuffers(aglGetCurrentContext());
1386 #elif GR_WIN32_BUILD
1387 SwapBuf();
1388 int set_a_break_pt_here = 9;
1389 SwapBuf();
1390 #endif
1391#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001392}
1393
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001394void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1395 uint32_t startVertex,
1396 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001397 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1398
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001399 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1400
1401 // our setupGeometry better have adjusted this to zero.
1402 // DrawElements doesn't take an offset so we always adjus the startVertex.
1403 GrAssert(0 == startVertex);
1404
1405 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1406 // account for startVertex in the DrawElements case. So we always
1407 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001408 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001409#if SWAP_PER_DRAW
1410 glFlush();
1411 #if GR_MAC_BUILD
1412 aglSwapBuffers(aglGetCurrentContext());
1413 int set_a_break_pt_here = 9;
1414 aglSwapBuffers(aglGetCurrentContext());
1415 #elif GR_WIN32_BUILD
1416 SwapBuf();
1417 int set_a_break_pt_here = 9;
1418 SwapBuf();
1419 #endif
1420#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001421}
1422
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001423void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001424
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001425 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001426 GrAssert(kNone_MSFBO != fMSFBOType);
1427 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001428 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001429 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001430 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001431 rt->textureFBOID()));
1432 #if GR_COLLECT_STATS
1433 ++fStats.fRenderTargetChngCnt;
1434 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001435 // make sure we go through flushRenderTarget() since we've modified
1436 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001437 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001438 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001439 const GrIRect dirtyRect = rt->getResolveRect();
1440 GrGLIRect r;
1441 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1442 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001443
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001444 if (kAppleES_MSFBO == fMSFBOType) {
1445 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001446 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001447 GR_GL(Scissor(r.fLeft, r.fBottom,
1448 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001449 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001450 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001451 fHWBounds.fScissorEnabled = true;
1452 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001453 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001454 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001455 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1456 flushScissor(NULL);
1457 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001458 int right = r.fLeft + r.fWidth;
1459 int top = r.fBottom + r.fHeight;
1460 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1461 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001462 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001463 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001464 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001465 }
1466}
1467
twiz@google.com0f31ca72011-03-18 17:38:11 +00001468static const GrGLenum grToGLStencilFunc[] = {
1469 GR_GL_ALWAYS, // kAlways_StencilFunc
1470 GR_GL_NEVER, // kNever_StencilFunc
1471 GR_GL_GREATER, // kGreater_StencilFunc
1472 GR_GL_GEQUAL, // kGEqual_StencilFunc
1473 GR_GL_LESS, // kLess_StencilFunc
1474 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1475 GR_GL_EQUAL, // kEqual_StencilFunc,
1476 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001477};
1478GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1479GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1480GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1481GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1482GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1483GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1484GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1485GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1486GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1487
twiz@google.com0f31ca72011-03-18 17:38:11 +00001488static const GrGLenum grToGLStencilOp[] = {
1489 GR_GL_KEEP, // kKeep_StencilOp
1490 GR_GL_REPLACE, // kReplace_StencilOp
1491 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1492 GR_GL_INCR, // kIncClamp_StencilOp
1493 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1494 GR_GL_DECR, // kDecClamp_StencilOp
1495 GR_GL_ZERO, // kZero_StencilOp
1496 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001497};
1498GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1499GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1500GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1501GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1502GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1503GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1504GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1505GR_STATIC_ASSERT(6 == kZero_StencilOp);
1506GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1507
reed@google.comac10a2d2010-12-22 21:39:39 +00001508void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001509 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001510
1511 // use stencil for clipping if clipping is enabled and the clip
1512 // has been written into the stencil.
1513 bool stencilClip = fClipState.fClipInStencil &&
1514 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001515 bool stencilChange = fHWStencilClip != stencilClip ||
1516 fHWDrawState.fStencilSettings != *settings ||
1517 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1518 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001519
1520 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001521
bsalomon@google.comd302f142011-03-03 13:54:13 +00001522 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1523 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001524
bsalomon@google.comd302f142011-03-03 13:54:13 +00001525 if (settings->isDisabled()) {
1526 if (stencilClip) {
1527 settings = &gClipStencilSettings;
1528 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001529 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001530
1531 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001532 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001533 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001534 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001535 #if GR_DEBUG
1536 if (!fStencilWrapOpsSupport) {
1537 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1538 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1539 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1540 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1541 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1542 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1543 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1544 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1545 }
1546 #endif
1547 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1548 GrAssert(stencilBits ||
1549 (GrStencilSettings::gDisabled ==
1550 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001551 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1552 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001553
1554 unsigned int frontRef = settings->fFrontFuncRef;
1555 unsigned int frontMask = settings->fFrontFuncMask;
1556 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001557 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001558
1559 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1560
1561 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1562 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1563 } else {
1564 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1565
1566 ConvertStencilFuncAndMask(settings->fFrontFunc,
1567 stencilClip,
1568 clipStencilMask,
1569 userStencilMask,
1570 &frontRef,
1571 &frontMask);
1572 frontWriteMask &= userStencilMask;
1573 }
1574 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001575 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001576 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001577 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001578 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001579 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001580 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001581 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001582 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001583 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001584
1585 unsigned int backRef = settings->fBackFuncRef;
1586 unsigned int backMask = settings->fBackFuncMask;
1587 unsigned int backWriteMask = settings->fBackWriteMask;
1588
1589
1590 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1591 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1592 backFunc = grToGLStencilFunc[settings->fBackFunc];
1593 } else {
1594 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1595 ConvertStencilFuncAndMask(settings->fBackFunc,
1596 stencilClip,
1597 clipStencilMask,
1598 userStencilMask,
1599 &backRef,
1600 &backMask);
1601 backWriteMask &= userStencilMask;
1602 }
1603
twiz@google.com0f31ca72011-03-18 17:38:11 +00001604 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1605 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1606 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1607 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1608 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001609 grToGLStencilOp[settings->fFrontPassOp],
1610 grToGLStencilOp[settings->fFrontPassOp]));
1611
twiz@google.com0f31ca72011-03-18 17:38:11 +00001612 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001613 grToGLStencilOp[settings->fBackPassOp],
1614 grToGLStencilOp[settings->fBackPassOp]));
1615 } else {
1616 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1617 GR_GL(StencilMask(frontWriteMask));
1618 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1619 grToGLStencilOp[settings->fFrontPassOp],
1620 grToGLStencilOp[settings->fFrontPassOp]));
1621 }
1622 }
1623 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001624 fHWStencilClip = stencilClip;
1625 }
1626}
1627
bsalomon@google.com0650e812011-04-08 18:07:53 +00001628bool GrGpuGL::useSmoothLines() {
1629 // there is a conflict between using smooth lines and our use of
1630 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1631 // but not in a premul-alpha way. So we only use them when our alpha
1632 // is 0xff.
1633
1634 // TODO: write a smarter line frag shader.
1635
1636 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1637 canDisableBlend();
1638}
1639
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001640void GrGpuGL::flushAAState(GrPrimitiveType type) {
1641 if (GR_GL_SUPPORT_DESKTOP) {
1642 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1643 // smooth lines.
1644
1645 // we prefer smooth lines over multisampled lines
1646 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001647 if (GrIsPrimTypeLines(type)) {
1648 bool smooth = useSmoothLines();
1649 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001650 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1651 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001652 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001653 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1654 fHWAAState.fSmoothLineEnabled = false;
1655 }
1656 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1657 fHWAAState.fMSAAEnabled) {
1658 GR_GL(Disable(GR_GL_MULTISAMPLE));
1659 fHWAAState.fMSAAEnabled = false;
1660 }
1661 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1662 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1663 fHWAAState.fMSAAEnabled) {
1664 if (fHWAAState.fMSAAEnabled) {
1665 GR_GL(Disable(GR_GL_MULTISAMPLE));
1666 fHWAAState.fMSAAEnabled = false;
1667 } else {
1668 GR_GL(Enable(GR_GL_MULTISAMPLE));
1669 fHWAAState.fMSAAEnabled = true;
1670 }
1671 }
1672 }
1673}
1674
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001675void GrGpuGL::flushBlend(GrPrimitiveType type,
1676 GrBlendCoeff srcCoeff,
1677 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001678 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1679 if (fHWBlendDisabled) {
1680 GR_GL(Enable(GR_GL_BLEND));
1681 fHWBlendDisabled = false;
1682 }
1683 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1684 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1685 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1686 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1687 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1688 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1689 }
1690 } else {
1691 bool blendOff = canDisableBlend();
1692 if (fHWBlendDisabled != blendOff) {
1693 if (blendOff) {
1694 GR_GL(Disable(GR_GL_BLEND));
1695 } else {
1696 GR_GL(Enable(GR_GL_BLEND));
1697 }
1698 fHWBlendDisabled = blendOff;
1699 }
1700 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001701 if (fHWDrawState.fSrcBlend != srcCoeff ||
1702 fHWDrawState.fDstBlend != dstCoeff) {
1703 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1704 gXfermodeCoeff2Blend[dstCoeff]));
1705 fHWDrawState.fSrcBlend = srcCoeff;
1706 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001707 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001708 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1709 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001710 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1711
1712 float c[] = {
1713 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1714 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1715 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1716 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1717 };
1718 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1719 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1720 }
1721 }
1722 }
1723}
1724
bsalomon@google.comffca4002011-02-22 20:34:01 +00001725bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001726
1727 // GrGpu::setupClipAndFlushState should have already checked this
1728 // and bailed if not true.
1729 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001730
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001731 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001732 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001733 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001734 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001735
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001736 // true for now, but maybe not with GrEffect.
1737 GrAssert(NULL != nextTexture);
1738 // if we created a rt/tex and rendered to it without using a
1739 // texture and now we're texuring from the rt it will still be
1740 // the last bound texture, but it needs resolving. So keep this
1741 // out of the "last != next" check.
1742 GrGLRenderTarget* texRT =
1743 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1744 if (NULL != texRT) {
1745 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001746 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001747
1748 if (fHWDrawState.fTextures[s] != nextTexture) {
1749 setTextureUnit(s);
1750 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1751 #if GR_COLLECT_STATS
1752 ++fStats.fTextureChngCnt;
1753 #endif
1754 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1755 fHWDrawState.fTextures[s] = nextTexture;
1756 }
1757
1758 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1759 const GrGLTexture::TexParams& oldTexParams =
1760 nextTexture->getTexParams();
1761 GrGLTexture::TexParams newTexParams;
1762
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001763 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1764 newTexParams.fFilter = GR_GL_NEAREST;
1765 } else {
1766 newTexParams.fFilter = GR_GL_LINEAR;
1767 }
1768
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001769 newTexParams.fWrapS =
1770 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1771 newTexParams.fWrapT =
1772 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1773
1774 if (newTexParams.fFilter != oldTexParams.fFilter) {
1775 setTextureUnit(s);
1776 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1777 GR_GL_TEXTURE_MAG_FILTER,
1778 newTexParams.fFilter));
1779 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1780 GR_GL_TEXTURE_MIN_FILTER,
1781 newTexParams.fFilter));
1782 }
1783 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1784 setTextureUnit(s);
1785 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1786 GR_GL_TEXTURE_WRAP_S,
1787 newTexParams.fWrapS));
1788 }
1789 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1790 setTextureUnit(s);
1791 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1792 GR_GL_TEXTURE_WRAP_T,
1793 newTexParams.fWrapT));
1794 }
1795 nextTexture->setTexParams(newTexParams);
1796
1797 // The texture matrix has to compensate for texture width/height
1798 // and NPOT-embedded-in-POT
1799 fDirtyFlags.fTextureChangedMask |= (1 << s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001800 }
1801 }
1802
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001803 GrIRect* rect = NULL;
1804 GrIRect clipBounds;
1805 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1806 fClip.hasConservativeBounds()) {
1807 fClip.getConservativeBounds().roundOut(&clipBounds);
1808 rect = &clipBounds;
1809 }
1810 this->flushRenderTarget(rect);
1811 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001812
reed@google.comac10a2d2010-12-22 21:39:39 +00001813 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1814 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1815 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001816 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001817 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001818 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001819 }
1820 }
1821
bsalomon@google.comd302f142011-03-03 13:54:13 +00001822 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1823 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001824 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001825 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001826 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001827 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001828 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001829 }
1830 GR_GL(ColorMask(mask, mask, mask, mask));
1831 }
1832
bsalomon@google.comd302f142011-03-03 13:54:13 +00001833 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1834 switch (fCurrDrawState.fDrawFace) {
1835 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001836 GR_GL(Enable(GR_GL_CULL_FACE));
1837 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001838 break;
1839 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001840 GR_GL(Enable(GR_GL_CULL_FACE));
1841 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001842 break;
1843 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001844 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001845 break;
1846 default:
1847 GrCrash("Unknown draw face.");
1848 }
1849 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1850 }
1851
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001852#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001853 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001854 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001855 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001856 NULL == fCurrDrawState.fRenderTarget ||
1857 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001858 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001859 fCurrDrawState.fRenderTarget);
1860 }
1861#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001862
reed@google.comac10a2d2010-12-22 21:39:39 +00001863 flushStencil();
1864
bsalomon@google.comd302f142011-03-03 13:54:13 +00001865 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001866 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001867 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001868}
1869
1870void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001871 if (fHWGeometryState.fVertexBuffer != buffer) {
1872 fHWGeometryState.fArrayPtrsDirty = true;
1873 fHWGeometryState.fVertexBuffer = buffer;
1874 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001875}
1876
1877void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001878 if (fHWGeometryState.fVertexBuffer == buffer) {
1879 // deleting bound buffer does implied bind to 0
1880 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001881 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001882 }
1883}
1884
1885void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1886 fGeometrySrc.fIndexBuffer = buffer;
1887}
1888
1889void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001890 if (fHWGeometryState.fIndexBuffer == buffer) {
1891 // deleting bound buffer does implied bind to 0
1892 fHWGeometryState.fIndexBuffer = NULL;
1893 }
1894}
1895
reed@google.comac10a2d2010-12-22 21:39:39 +00001896void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1897 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001898 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001899 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001900 }
1901 if (fHWDrawState.fRenderTarget == renderTarget) {
1902 fHWDrawState.fRenderTarget = NULL;
1903 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001904}
1905
1906void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001907 for (int s = 0; s < kNumStages; ++s) {
1908 if (fCurrDrawState.fTextures[s] == texture) {
1909 fCurrDrawState.fTextures[s] = NULL;
1910 }
1911 if (fHWDrawState.fTextures[s] == texture) {
1912 // deleting bound texture does implied bind to 0
1913 fHWDrawState.fTextures[s] = NULL;
1914 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001915 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001916}
1917
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001918bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001919 GrGLenum* internalFormat,
1920 GrGLenum* format,
1921 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001922 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001923 case kRGBA_8888_GrPixelConfig:
1924 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001925 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001926 if (GR_GL_SUPPORT_ES) {
1927 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1928 // format for a BGRA is BGRA not RGBA (as on desktop)
1929 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1930 } else {
1931 *internalFormat = GR_GL_RGBA;
1932 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001933 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001934 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001935 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001936 *format = GR_GL_RGB;
1937 *internalFormat = GR_GL_RGB;
1938 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001939 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001940 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001941 *format = GR_GL_RGBA;
1942 *internalFormat = GR_GL_RGBA;
1943 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001944 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001945 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001946 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001947 *format = GR_GL_PALETTE8_RGBA8;
1948 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001949 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001950 } else {
1951 return false;
1952 }
1953 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001954 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001955 *format = GR_GL_ALPHA;
1956 *internalFormat = GR_GL_ALPHA;
1957 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001958 break;
1959 default:
1960 return false;
1961 }
1962 return true;
1963}
1964
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001965void GrGpuGL::setTextureUnit(int unit) {
1966 GrAssert(unit >= 0 && unit < kNumStages);
1967 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001968 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001969 fActiveTextureUnitIdx = unit;
1970 }
1971}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001972
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001973void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001974 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1975 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001976 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1977 }
1978}
1979
reed@google.comac10a2d2010-12-22 21:39:39 +00001980/* On ES the internalFormat and format must match for TexImage and we use
1981 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1982 decide the internalFormat. However, on ES internalFormat for
1983 RenderBufferStorage* has to be a specific format (not a base format like
1984 GL_RGBA).
1985 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001986bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001987 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001988 case kRGBA_8888_GrPixelConfig:
1989 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001990 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001991 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001992 return true;
1993 } else {
1994 return false;
1995 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001996 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001997 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1998 // with FBO extension desktop GL has
1999 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002000 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002001 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002002 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002003 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002004 return true;
2005 default:
2006 return false;
2007 }
2008}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002009
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002010void GrGpuGL::resetDirtyFlags() {
2011 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2012}
2013
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002014void GrGpuGL::setBuffers(bool indexed,
2015 int* extraVertexOffset,
2016 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002017
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002018 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002019
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002020 GrGLVertexBuffer* vbuf;
2021 switch (fGeometrySrc.fVertexSrc) {
2022 case kBuffer_GeometrySrcType:
2023 *extraVertexOffset = 0;
2024 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2025 break;
2026 case kArray_GeometrySrcType:
2027 case kReserved_GeometrySrcType:
2028 finalizeReservedVertices();
2029 *extraVertexOffset = fCurrPoolStartVertex;
2030 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2031 break;
2032 default:
2033 vbuf = NULL; // suppress warning
2034 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002035 }
2036
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002037 GrAssert(NULL != vbuf);
2038 GrAssert(!vbuf->isLocked());
2039 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002040 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002041 fHWGeometryState.fArrayPtrsDirty = true;
2042 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002043 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002044
2045 if (indexed) {
2046 GrAssert(NULL != extraIndexOffset);
2047
2048 GrGLIndexBuffer* ibuf;
2049 switch (fGeometrySrc.fIndexSrc) {
2050 case kBuffer_GeometrySrcType:
2051 *extraIndexOffset = 0;
2052 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2053 break;
2054 case kArray_GeometrySrcType:
2055 case kReserved_GeometrySrcType:
2056 finalizeReservedIndices();
2057 *extraIndexOffset = fCurrPoolStartIndex;
2058 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2059 break;
2060 default:
2061 ibuf = NULL; // suppress warning
2062 GrCrash("Unknown geometry src type!");
2063 }
2064
2065 GrAssert(NULL != ibuf);
2066 GrAssert(!ibuf->isLocked());
2067 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002068 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002069 fHWGeometryState.fIndexBuffer = ibuf;
2070 }
2071 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002072}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002073
2074int GrGpuGL::getMaxEdges() const {
2075 // FIXME: This is a pessimistic estimate based on how many other things
2076 // want to add uniforms. This should be centralized somewhere.
2077 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2078}