blob: 70686d7e685bda5268ecd92661d4a4aae47aba4e [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 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1007 status, desc.fWidth, desc.fHeight);
1008 continue;
1009 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001010 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001011 #if GR_COLLECT_STATS
1012 ++fStats.fRenderTargetChngCnt;
1013 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001014 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1015 GR_GL_COLOR_ATTACHMENT0,
1016 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001017 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001018
1019 }
1020 if (rtIDs.fStencilRenderbufferID) {
1021 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001022 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1023 GR_GL_STENCIL_ATTACHMENT,
1024 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001025 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001026 // if it is a packed format bind to depth also, otherwise
1027 // we may get an unsupported fbo completeness result
1028 if (stencilFormats[i].fPacked) {
1029 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1030 GR_GL_DEPTH_ATTACHMENT,
1031 GR_GL_RENDERBUFFER,
1032 rtIDs.fStencilRenderbufferID));
1033 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001034 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001035 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001036
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001037 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001038 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1039 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001040 // undo the depth bind
1041 if (rtIDs.fStencilRenderbufferID &&
1042 stencilFormats[i].fPacked) {
1043 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1044 GR_GL_DEPTH_ATTACHMENT,
1045 GR_GL_RENDERBUFFER,
1046 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001047 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001048 continue;
1049 }
1050 // we're successful!
1051 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001052 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001053 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001054 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001055 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001056 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001057 }
1058 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001059 break;
1060 }
1061 if (failed) {
1062 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001063 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001064 }
1065 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001066 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001067 }
1068 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001069 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001070 }
1071 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001072 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001073 }
1074 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1075 return return_null_texture();
1076 }
1077 }
1078#ifdef TRACE_TEXTURE_CREATION
1079 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1080 tex->fTextureID, width, height, tex->fUploadByteCount);
1081#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001082 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001083
1084 if (0 != rtIDs.fTexFBOID) {
1085 GrRenderTarget* rt = tex->asRenderTarget();
1086 // We've messed with FBO state but may not have set the correct viewport
1087 // so just dirty the rendertarget state to force a resend.
1088 fHWDrawState.fRenderTarget = NULL;
1089
1090 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001091 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001092 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1093 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001094 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001095 fCurrDrawState.fRenderTarget = rtSave;
1096 }
1097 }
1098 return tex;
1099}
1100
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001101GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001102 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001103 GR_GL(GenBuffers(1, &id));
1104 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001105 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001106 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001107 GrGLClearErr();
1108 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001109 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1110 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1111 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001112 GR_GL(DeleteBuffers(1, &id));
1113 // deleting bound buffer does implicit bind to 0
1114 fHWGeometryState.fVertexBuffer = NULL;
1115 return NULL;
1116 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001117 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001118 size, dynamic);
1119 fHWGeometryState.fVertexBuffer = vertexBuffer;
1120 return vertexBuffer;
1121 }
1122 return NULL;
1123}
1124
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001125GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001126 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001127 GR_GL(GenBuffers(1, &id));
1128 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001129 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001130 GrGLClearErr();
1131 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001132 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1133 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1134 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001135 GR_GL(DeleteBuffers(1, &id));
1136 // deleting bound buffer does implicit bind to 0
1137 fHWGeometryState.fIndexBuffer = NULL;
1138 return NULL;
1139 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001140 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001141 size, dynamic);
1142 fHWGeometryState.fIndexBuffer = indexBuffer;
1143 return indexBuffer;
1144 }
1145 return NULL;
1146}
1147
reed@google.comac10a2d2010-12-22 21:39:39 +00001148void GrGpuGL::flushScissor(const GrIRect* rect) {
1149 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001150 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001151 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001152
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001153 GrGLIRect scissor;
1154 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001155 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001156 rect->width(), rect->height());
1157 if (scissor.contains(vp)) {
1158 rect = NULL;
1159 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001160 }
1161
1162 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001163 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001164 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001165 fHWBounds.fScissorRect = scissor;
1166 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001167 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001168 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001169 fHWBounds.fScissorEnabled = true;
1170 }
1171 } else {
1172 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001173 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001174 fHWBounds.fScissorEnabled = false;
1175 }
1176 }
1177}
1178
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001179void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001180 if (NULL == fCurrDrawState.fRenderTarget) {
1181 return;
1182 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001183 GrIRect r;
1184 if (NULL != rect) {
1185 // flushScissor expects rect to be clipped to the target.
1186 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001187 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1188 fCurrDrawState.fRenderTarget->height());
1189 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001190 rect = &r;
1191 } else {
1192 return;
1193 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001194 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001195 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001196 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001197 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001198 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001199 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1200 GrColorUnpackG(color)/255.f,
1201 GrColorUnpackB(color)/255.f,
1202 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001203 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001204}
1205
bsalomon@google.com398109c2011-04-14 18:40:27 +00001206void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001207 if (NULL == fCurrDrawState.fRenderTarget) {
1208 return;
1209 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001210
1211 this->flushRenderTarget(&GrIRect::EmptyIRect());
1212
reed@google.comac10a2d2010-12-22 21:39:39 +00001213 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001214 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001215 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001216 }
1217 GR_GL(StencilMask(mask));
1218 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001219 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001220 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001221}
1222
bsalomon@google.com398109c2011-04-14 18:40:27 +00001223void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001224 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001225#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001226 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001227 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001228 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001229#else
1230 // we could just clear the clip bit but when we go through
1231 // angle a partial stencil mask will cause clears to be
1232 // turned into draws. Our contract on GrDrawTarget says that
1233 // changing the clip between stencil passes may or may not
1234 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001235 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001236#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001237 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001238 flushScissor(&rect);
1239 GR_GL(StencilMask(clipStencilMask));
1240 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001241 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001242 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001243}
1244
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001245void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001246 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001247}
1248
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001249bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1250 int left, int top, int width, int height,
1251 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001252 GrGLenum internalFormat; // we don't use this for glReadPixels
1253 GrGLenum format;
1254 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001255 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1256 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001257 }
1258 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1259 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1260 switch (tgt->getResolveType()) {
1261 case GrGLRenderTarget::kCantResolve_ResolveType:
1262 return false;
1263 case GrGLRenderTarget::kAutoResolves_ResolveType:
1264 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1265 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001266 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001267 break;
1268 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001269 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001270 // we don't track the state of the READ FBO ID.
1271 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1272 break;
1273 default:
1274 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001275 }
1276
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001277 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001278
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001279 // the read rect is viewport-relative
1280 GrGLIRect readRect;
1281 readRect.setRelativeTo(glvp, left, top, width, height);
1282 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001283 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001284 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001285
1286 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1287 // API presents top-to-bottom
1288 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001289 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001290 GrAutoMalloc rowStorage(stride);
1291 void* tmp = rowStorage.get();
1292
1293 const int halfY = height >> 1;
1294 char* top = reinterpret_cast<char*>(buffer);
1295 char* bottom = top + (height - 1) * stride;
1296 for (int y = 0; y < halfY; y++) {
1297 memcpy(tmp, top, stride);
1298 memcpy(top, bottom, stride);
1299 memcpy(bottom, tmp, stride);
1300 top += stride;
1301 bottom -= stride;
1302 }
1303 }
1304 return true;
1305}
1306
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001307void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001308
1309 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1310
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001311 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001312 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001313 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001314 #if GR_COLLECT_STATS
1315 ++fStats.fRenderTargetChngCnt;
1316 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001317 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001318 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1319 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001320 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1321 }
1322 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001323 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001324 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001325 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001326 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001327 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001328 fHWBounds.fViewportRect = vp;
1329 }
1330 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001331 if (NULL == bound || !bound->isEmpty()) {
1332 rt->flagAsNeedingResolve(bound);
1333 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001334}
1335
twiz@google.com0f31ca72011-03-18 17:38:11 +00001336GrGLenum gPrimitiveType2GLMode[] = {
1337 GR_GL_TRIANGLES,
1338 GR_GL_TRIANGLE_STRIP,
1339 GR_GL_TRIANGLE_FAN,
1340 GR_GL_POINTS,
1341 GR_GL_LINES,
1342 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001343};
1344
bsalomon@google.comd302f142011-03-03 13:54:13 +00001345#define SWAP_PER_DRAW 0
1346
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001347#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001348 #if GR_MAC_BUILD
1349 #include <AGL/agl.h>
1350 #elif GR_WIN32_BUILD
1351 void SwapBuf() {
1352 DWORD procID = GetCurrentProcessId();
1353 HWND hwnd = GetTopWindow(GetDesktopWindow());
1354 while(hwnd) {
1355 DWORD wndProcID = 0;
1356 GetWindowThreadProcessId(hwnd, &wndProcID);
1357 if(wndProcID == procID) {
1358 SwapBuffers(GetDC(hwnd));
1359 }
1360 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1361 }
1362 }
1363 #endif
1364#endif
1365
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001366void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1367 uint32_t startVertex,
1368 uint32_t startIndex,
1369 uint32_t vertexCount,
1370 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001371 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1372
twiz@google.com0f31ca72011-03-18 17:38:11 +00001373 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001374
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001375 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1376 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1377
1378 // our setupGeometry better have adjusted this to zero since
1379 // DrawElements always draws from the begining of the arrays for idx 0.
1380 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001381
1382 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001383 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001384#if SWAP_PER_DRAW
1385 glFlush();
1386 #if GR_MAC_BUILD
1387 aglSwapBuffers(aglGetCurrentContext());
1388 int set_a_break_pt_here = 9;
1389 aglSwapBuffers(aglGetCurrentContext());
1390 #elif GR_WIN32_BUILD
1391 SwapBuf();
1392 int set_a_break_pt_here = 9;
1393 SwapBuf();
1394 #endif
1395#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001396}
1397
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001398void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1399 uint32_t startVertex,
1400 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001401 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1402
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001403 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1404
1405 // our setupGeometry better have adjusted this to zero.
1406 // DrawElements doesn't take an offset so we always adjus the startVertex.
1407 GrAssert(0 == startVertex);
1408
1409 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1410 // account for startVertex in the DrawElements case. So we always
1411 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001412 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001413#if SWAP_PER_DRAW
1414 glFlush();
1415 #if GR_MAC_BUILD
1416 aglSwapBuffers(aglGetCurrentContext());
1417 int set_a_break_pt_here = 9;
1418 aglSwapBuffers(aglGetCurrentContext());
1419 #elif GR_WIN32_BUILD
1420 SwapBuf();
1421 int set_a_break_pt_here = 9;
1422 SwapBuf();
1423 #endif
1424#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001425}
1426
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001427void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001428
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001429 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001430 GrAssert(kNone_MSFBO != fMSFBOType);
1431 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001432 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001433 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001434 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001435 rt->textureFBOID()));
1436 #if GR_COLLECT_STATS
1437 ++fStats.fRenderTargetChngCnt;
1438 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001439 // make sure we go through flushRenderTarget() since we've modified
1440 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001441 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001442 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001443 const GrIRect dirtyRect = rt->getResolveRect();
1444 GrGLIRect r;
1445 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1446 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001447
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001448 if (kAppleES_MSFBO == fMSFBOType) {
1449 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001450 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001451 GR_GL(Scissor(r.fLeft, r.fBottom,
1452 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001453 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001454 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001455 fHWBounds.fScissorEnabled = true;
1456 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001457 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001458 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001459 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1460 flushScissor(NULL);
1461 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001462 int right = r.fLeft + r.fWidth;
1463 int top = r.fBottom + r.fHeight;
1464 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1465 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001466 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001467 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001468 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001469 }
1470}
1471
twiz@google.com0f31ca72011-03-18 17:38:11 +00001472static const GrGLenum grToGLStencilFunc[] = {
1473 GR_GL_ALWAYS, // kAlways_StencilFunc
1474 GR_GL_NEVER, // kNever_StencilFunc
1475 GR_GL_GREATER, // kGreater_StencilFunc
1476 GR_GL_GEQUAL, // kGEqual_StencilFunc
1477 GR_GL_LESS, // kLess_StencilFunc
1478 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1479 GR_GL_EQUAL, // kEqual_StencilFunc,
1480 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001481};
1482GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1483GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1484GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1485GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1486GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1487GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1488GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1489GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1490GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1491
twiz@google.com0f31ca72011-03-18 17:38:11 +00001492static const GrGLenum grToGLStencilOp[] = {
1493 GR_GL_KEEP, // kKeep_StencilOp
1494 GR_GL_REPLACE, // kReplace_StencilOp
1495 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1496 GR_GL_INCR, // kIncClamp_StencilOp
1497 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1498 GR_GL_DECR, // kDecClamp_StencilOp
1499 GR_GL_ZERO, // kZero_StencilOp
1500 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001501};
1502GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1503GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1504GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1505GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1506GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1507GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1508GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1509GR_STATIC_ASSERT(6 == kZero_StencilOp);
1510GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1511
reed@google.comac10a2d2010-12-22 21:39:39 +00001512void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001513 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001514
1515 // use stencil for clipping if clipping is enabled and the clip
1516 // has been written into the stencil.
1517 bool stencilClip = fClipState.fClipInStencil &&
1518 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001519 bool stencilChange = fHWStencilClip != stencilClip ||
1520 fHWDrawState.fStencilSettings != *settings ||
1521 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1522 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001523
1524 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001525
bsalomon@google.comd302f142011-03-03 13:54:13 +00001526 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1527 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001528
bsalomon@google.comd302f142011-03-03 13:54:13 +00001529 if (settings->isDisabled()) {
1530 if (stencilClip) {
1531 settings = &gClipStencilSettings;
1532 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001533 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001534
1535 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001536 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001537 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001538 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001539 #if GR_DEBUG
1540 if (!fStencilWrapOpsSupport) {
1541 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1542 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1543 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1544 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1545 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1546 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1547 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1548 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1549 }
1550 #endif
1551 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1552 GrAssert(stencilBits ||
1553 (GrStencilSettings::gDisabled ==
1554 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001555 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1556 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001557
1558 unsigned int frontRef = settings->fFrontFuncRef;
1559 unsigned int frontMask = settings->fFrontFuncMask;
1560 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001561 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001562
1563 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1564
1565 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1566 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1567 } else {
1568 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1569
1570 ConvertStencilFuncAndMask(settings->fFrontFunc,
1571 stencilClip,
1572 clipStencilMask,
1573 userStencilMask,
1574 &frontRef,
1575 &frontMask);
1576 frontWriteMask &= userStencilMask;
1577 }
1578 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001579 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001580 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001581 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001582 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001583 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001584 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001585 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001586 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001587 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001588
1589 unsigned int backRef = settings->fBackFuncRef;
1590 unsigned int backMask = settings->fBackFuncMask;
1591 unsigned int backWriteMask = settings->fBackWriteMask;
1592
1593
1594 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1595 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1596 backFunc = grToGLStencilFunc[settings->fBackFunc];
1597 } else {
1598 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1599 ConvertStencilFuncAndMask(settings->fBackFunc,
1600 stencilClip,
1601 clipStencilMask,
1602 userStencilMask,
1603 &backRef,
1604 &backMask);
1605 backWriteMask &= userStencilMask;
1606 }
1607
twiz@google.com0f31ca72011-03-18 17:38:11 +00001608 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1609 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1610 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1611 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1612 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001613 grToGLStencilOp[settings->fFrontPassOp],
1614 grToGLStencilOp[settings->fFrontPassOp]));
1615
twiz@google.com0f31ca72011-03-18 17:38:11 +00001616 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001617 grToGLStencilOp[settings->fBackPassOp],
1618 grToGLStencilOp[settings->fBackPassOp]));
1619 } else {
1620 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1621 GR_GL(StencilMask(frontWriteMask));
1622 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1623 grToGLStencilOp[settings->fFrontPassOp],
1624 grToGLStencilOp[settings->fFrontPassOp]));
1625 }
1626 }
1627 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001628 fHWStencilClip = stencilClip;
1629 }
1630}
1631
bsalomon@google.com0650e812011-04-08 18:07:53 +00001632bool GrGpuGL::useSmoothLines() {
1633 // there is a conflict between using smooth lines and our use of
1634 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1635 // but not in a premul-alpha way. So we only use them when our alpha
1636 // is 0xff.
1637
1638 // TODO: write a smarter line frag shader.
1639
1640 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1641 canDisableBlend();
1642}
1643
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001644void GrGpuGL::flushAAState(GrPrimitiveType type) {
1645 if (GR_GL_SUPPORT_DESKTOP) {
1646 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1647 // smooth lines.
1648
1649 // we prefer smooth lines over multisampled lines
1650 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001651 if (GrIsPrimTypeLines(type)) {
1652 bool smooth = useSmoothLines();
1653 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001654 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1655 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001656 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001657 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1658 fHWAAState.fSmoothLineEnabled = false;
1659 }
1660 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1661 fHWAAState.fMSAAEnabled) {
1662 GR_GL(Disable(GR_GL_MULTISAMPLE));
1663 fHWAAState.fMSAAEnabled = false;
1664 }
1665 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1666 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1667 fHWAAState.fMSAAEnabled) {
1668 if (fHWAAState.fMSAAEnabled) {
1669 GR_GL(Disable(GR_GL_MULTISAMPLE));
1670 fHWAAState.fMSAAEnabled = false;
1671 } else {
1672 GR_GL(Enable(GR_GL_MULTISAMPLE));
1673 fHWAAState.fMSAAEnabled = true;
1674 }
1675 }
1676 }
1677}
1678
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001679void GrGpuGL::flushBlend(GrPrimitiveType type,
1680 GrBlendCoeff srcCoeff,
1681 GrBlendCoeff dstCoeff) {
bsalomon@google.com0650e812011-04-08 18:07:53 +00001682 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1683 if (fHWBlendDisabled) {
1684 GR_GL(Enable(GR_GL_BLEND));
1685 fHWBlendDisabled = false;
1686 }
1687 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1688 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1689 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1690 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1691 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1692 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1693 }
1694 } else {
1695 bool blendOff = canDisableBlend();
1696 if (fHWBlendDisabled != blendOff) {
1697 if (blendOff) {
1698 GR_GL(Disable(GR_GL_BLEND));
1699 } else {
1700 GR_GL(Enable(GR_GL_BLEND));
1701 }
1702 fHWBlendDisabled = blendOff;
1703 }
1704 if (!blendOff) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001705 if (fHWDrawState.fSrcBlend != srcCoeff ||
1706 fHWDrawState.fDstBlend != dstCoeff) {
1707 GR_GL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
1708 gXfermodeCoeff2Blend[dstCoeff]));
1709 fHWDrawState.fSrcBlend = srcCoeff;
1710 fHWDrawState.fDstBlend = dstCoeff;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001711 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +00001712 if ((BlendCoeffReferencesConstant(srcCoeff) ||
1713 BlendCoeffReferencesConstant(dstCoeff)) &&
bsalomon@google.com0650e812011-04-08 18:07:53 +00001714 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1715
1716 float c[] = {
1717 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1718 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1719 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1720 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1721 };
1722 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1723 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1724 }
1725 }
1726 }
1727}
1728
bsalomon@google.comffca4002011-02-22 20:34:01 +00001729bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001730
1731 // GrGpu::setupClipAndFlushState should have already checked this
1732 // and bailed if not true.
1733 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001734
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001735 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001736 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001737 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001738 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001739
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001740 // true for now, but maybe not with GrEffect.
1741 GrAssert(NULL != nextTexture);
1742 // if we created a rt/tex and rendered to it without using a
1743 // texture and now we're texuring from the rt it will still be
1744 // the last bound texture, but it needs resolving. So keep this
1745 // out of the "last != next" check.
1746 GrGLRenderTarget* texRT =
1747 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1748 if (NULL != texRT) {
1749 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001750 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001751
1752 if (fHWDrawState.fTextures[s] != nextTexture) {
1753 setTextureUnit(s);
1754 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1755 #if GR_COLLECT_STATS
1756 ++fStats.fTextureChngCnt;
1757 #endif
1758 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1759 fHWDrawState.fTextures[s] = nextTexture;
1760 }
1761
1762 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1763 const GrGLTexture::TexParams& oldTexParams =
1764 nextTexture->getTexParams();
1765 GrGLTexture::TexParams newTexParams;
1766
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001767 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1768 newTexParams.fFilter = GR_GL_NEAREST;
1769 } else {
1770 newTexParams.fFilter = GR_GL_LINEAR;
1771 }
1772
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001773 newTexParams.fWrapS =
1774 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1775 newTexParams.fWrapT =
1776 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1777
1778 if (newTexParams.fFilter != oldTexParams.fFilter) {
1779 setTextureUnit(s);
1780 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1781 GR_GL_TEXTURE_MAG_FILTER,
1782 newTexParams.fFilter));
1783 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1784 GR_GL_TEXTURE_MIN_FILTER,
1785 newTexParams.fFilter));
1786 }
1787 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1788 setTextureUnit(s);
1789 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1790 GR_GL_TEXTURE_WRAP_S,
1791 newTexParams.fWrapS));
1792 }
1793 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1794 setTextureUnit(s);
1795 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1796 GR_GL_TEXTURE_WRAP_T,
1797 newTexParams.fWrapT));
1798 }
1799 nextTexture->setTexParams(newTexParams);
1800
1801 // The texture matrix has to compensate for texture width/height
1802 // and NPOT-embedded-in-POT
1803 fDirtyFlags.fTextureChangedMask |= (1 << s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001804 }
1805 }
1806
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001807 GrIRect* rect = NULL;
1808 GrIRect clipBounds;
1809 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1810 fClip.hasConservativeBounds()) {
1811 fClip.getConservativeBounds().roundOut(&clipBounds);
1812 rect = &clipBounds;
1813 }
1814 this->flushRenderTarget(rect);
1815 this->flushAAState(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001816
reed@google.comac10a2d2010-12-22 21:39:39 +00001817 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1818 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1819 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001820 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001821 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001822 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001823 }
1824 }
1825
bsalomon@google.comd302f142011-03-03 13:54:13 +00001826 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1827 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001828 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001829 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001830 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001831 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001832 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001833 }
1834 GR_GL(ColorMask(mask, mask, mask, mask));
1835 }
1836
bsalomon@google.comd302f142011-03-03 13:54:13 +00001837 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1838 switch (fCurrDrawState.fDrawFace) {
1839 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001840 GR_GL(Enable(GR_GL_CULL_FACE));
1841 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001842 break;
1843 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001844 GR_GL(Enable(GR_GL_CULL_FACE));
1845 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001846 break;
1847 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001848 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001849 break;
1850 default:
1851 GrCrash("Unknown draw face.");
1852 }
1853 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1854 }
1855
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001856#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001857 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001858 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001859 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001860 NULL == fCurrDrawState.fRenderTarget ||
1861 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001862 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001863 fCurrDrawState.fRenderTarget);
1864 }
1865#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001866
reed@google.comac10a2d2010-12-22 21:39:39 +00001867 flushStencil();
1868
bsalomon@google.comd302f142011-03-03 13:54:13 +00001869 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001870 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001871 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001872}
1873
1874void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001875 if (fHWGeometryState.fVertexBuffer != buffer) {
1876 fHWGeometryState.fArrayPtrsDirty = true;
1877 fHWGeometryState.fVertexBuffer = buffer;
1878 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001879}
1880
1881void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001882 if (fHWGeometryState.fVertexBuffer == buffer) {
1883 // deleting bound buffer does implied bind to 0
1884 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001885 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001886 }
1887}
1888
1889void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1890 fGeometrySrc.fIndexBuffer = buffer;
1891}
1892
1893void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001894 if (fHWGeometryState.fIndexBuffer == buffer) {
1895 // deleting bound buffer does implied bind to 0
1896 fHWGeometryState.fIndexBuffer = NULL;
1897 }
1898}
1899
reed@google.comac10a2d2010-12-22 21:39:39 +00001900void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1901 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001902 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001903 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001904 }
1905 if (fHWDrawState.fRenderTarget == renderTarget) {
1906 fHWDrawState.fRenderTarget = NULL;
1907 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001908}
1909
1910void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001911 for (int s = 0; s < kNumStages; ++s) {
1912 if (fCurrDrawState.fTextures[s] == texture) {
1913 fCurrDrawState.fTextures[s] = NULL;
1914 }
1915 if (fHWDrawState.fTextures[s] == texture) {
1916 // deleting bound texture does implied bind to 0
1917 fHWDrawState.fTextures[s] = NULL;
1918 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001919 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001920}
1921
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001922bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001923 GrGLenum* internalFormat,
1924 GrGLenum* format,
1925 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001926 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001927 case kRGBA_8888_GrPixelConfig:
1928 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001929 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001930 if (GR_GL_SUPPORT_ES) {
1931 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1932 // format for a BGRA is BGRA not RGBA (as on desktop)
1933 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1934 } else {
1935 *internalFormat = GR_GL_RGBA;
1936 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001937 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001938 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001939 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001940 *format = GR_GL_RGB;
1941 *internalFormat = GR_GL_RGB;
1942 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001943 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001944 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001945 *format = GR_GL_RGBA;
1946 *internalFormat = GR_GL_RGBA;
1947 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001948 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001949 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001950 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001951 *format = GR_GL_PALETTE8_RGBA8;
1952 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001953 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001954 } else {
1955 return false;
1956 }
1957 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001958 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001959 *format = GR_GL_ALPHA;
1960 *internalFormat = GR_GL_ALPHA;
1961 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001962 break;
1963 default:
1964 return false;
1965 }
1966 return true;
1967}
1968
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001969void GrGpuGL::setTextureUnit(int unit) {
1970 GrAssert(unit >= 0 && unit < kNumStages);
1971 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001972 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001973 fActiveTextureUnitIdx = unit;
1974 }
1975}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001976
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001977void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001978 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1979 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001980 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1981 }
1982}
1983
reed@google.comac10a2d2010-12-22 21:39:39 +00001984/* On ES the internalFormat and format must match for TexImage and we use
1985 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1986 decide the internalFormat. However, on ES internalFormat for
1987 RenderBufferStorage* has to be a specific format (not a base format like
1988 GL_RGBA).
1989 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001990bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001991 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001992 case kRGBA_8888_GrPixelConfig:
1993 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001994 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001995 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001996 return true;
1997 } else {
1998 return false;
1999 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002000 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002001 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2002 // with FBO extension desktop GL has
2003 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002004 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002005 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002006 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002007 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002008 return true;
2009 default:
2010 return false;
2011 }
2012}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002013
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002014void GrGpuGL::resetDirtyFlags() {
2015 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2016}
2017
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002018void GrGpuGL::setBuffers(bool indexed,
2019 int* extraVertexOffset,
2020 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002021
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002022 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002023
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002024 GrGLVertexBuffer* vbuf;
2025 switch (fGeometrySrc.fVertexSrc) {
2026 case kBuffer_GeometrySrcType:
2027 *extraVertexOffset = 0;
2028 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2029 break;
2030 case kArray_GeometrySrcType:
2031 case kReserved_GeometrySrcType:
2032 finalizeReservedVertices();
2033 *extraVertexOffset = fCurrPoolStartVertex;
2034 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2035 break;
2036 default:
2037 vbuf = NULL; // suppress warning
2038 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002039 }
2040
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002041 GrAssert(NULL != vbuf);
2042 GrAssert(!vbuf->isLocked());
2043 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002044 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002045 fHWGeometryState.fArrayPtrsDirty = true;
2046 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002047 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002048
2049 if (indexed) {
2050 GrAssert(NULL != extraIndexOffset);
2051
2052 GrGLIndexBuffer* ibuf;
2053 switch (fGeometrySrc.fIndexSrc) {
2054 case kBuffer_GeometrySrcType:
2055 *extraIndexOffset = 0;
2056 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2057 break;
2058 case kArray_GeometrySrcType:
2059 case kReserved_GeometrySrcType:
2060 finalizeReservedIndices();
2061 *extraIndexOffset = fCurrPoolStartIndex;
2062 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2063 break;
2064 default:
2065 ibuf = NULL; // suppress warning
2066 GrCrash("Unknown geometry src type!");
2067 }
2068
2069 GrAssert(NULL != ibuf);
2070 GrAssert(!ibuf->isLocked());
2071 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002072 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002073 fHWGeometryState.fIndexBuffer = ibuf;
2074 }
2075 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002076}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002077
2078int GrGpuGL::getMaxEdges() const {
2079 // FIXME: This is a pessimistic estimate based on how many other things
2080 // want to add uniforms. This should be centralized somewhere.
2081 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2082}