blob: 5a2d2bd042dd64c4262970095b2d46ae1143c41c [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,
reed@google.comac10a2d2010-12-22 21:39:39 +000045};
46
bsalomon@google.com080773c2011-03-15 19:09:25 +000047bool GrGpuGL::BlendCoefReferencesConstant(GrBlendCoeff coeff) {
48 static const bool gCoeffReferencesBlendConst[] = {
49 false,
50 false,
51 false,
52 false,
53 false,
54 false,
55 false,
56 false,
57 false,
58 false,
59 true,
60 true,
61 true,
62 true,
63 };
64 return gCoeffReferencesBlendConst[coeff];
65 GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
66}
67
68GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
69GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
70GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
71GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
72GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
73GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
74GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
75GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
76GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
77GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
78GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
79GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
80GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
81GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
82
83GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
84
reed@google.comac10a2d2010-12-22 21:39:39 +000085///////////////////////////////////////////////////////////////////////////////
86
bsalomon@google.comd302f142011-03-03 13:54:13 +000087void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
88 GrSamplerState::SampleMode mode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000089 GrMatrix* matrix) {
90 GrAssert(NULL != texture);
91 GrAssert(NULL != matrix);
92 if (GR_Scalar1 != texture->contentScaleX() ||
93 GR_Scalar1 != texture->contentScaleY()) {
94 if (GrSamplerState::kRadial_SampleMode == mode) {
95 GrMatrix scale;
96 scale.setScale(texture->contentScaleX(), texture->contentScaleX());
97 matrix->postConcat(scale);
98 } else if (GrSamplerState::kNormal_SampleMode == mode) {
99 GrMatrix scale;
100 scale.setScale(texture->contentScaleX(), texture->contentScaleY());
101 matrix->postConcat(scale);
102 } else {
103 GrPrintf("We haven't handled NPOT adjustment for other sample modes!");
104 }
105 }
106 GrGLTexture::Orientation orientation = texture->orientation();
107 if (GrGLTexture::kBottomUp_Orientation == orientation) {
108 GrMatrix invY;
109 invY.setAll(GR_Scalar1, 0, 0,
110 0, -GR_Scalar1, GR_Scalar1,
111 0, 0, GrMatrix::I()[8]);
112 matrix->postConcat(invY);
113 } else {
114 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
115 }
116}
117
bsalomon@google.comd302f142011-03-03 13:54:13 +0000118bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000119 const GrSamplerState& sampler) {
120 GrAssert(NULL != texture);
121 if (!sampler.getMatrix().isIdentity()) {
122 return false;
123 }
124 if (GR_Scalar1 != texture->contentScaleX() ||
125 GR_Scalar1 != texture->contentScaleY()) {
126 return false;
127 }
128 GrGLTexture::Orientation orientation = texture->orientation();
129 if (GrGLTexture::kBottomUp_Orientation == orientation) {
130 return false;
131 } else {
132 GrAssert(GrGLTexture::kTopDown_Orientation == orientation);
133 }
134 return true;
135}
136
137///////////////////////////////////////////////////////////////////////////////
138
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000139static bool gPrintStartupSpew;
140
twiz@google.com59a190b2011-03-14 21:23:01 +0000141static bool fbo_test(int w, int h) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000142
twiz@google.com0f31ca72011-03-18 17:38:11 +0000143 GrGLint savedFBO;
144 GrGLint savedTexUnit;
145 GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000146 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO);
bsalomon@google.com316f99232011-01-13 21:28:12 +0000147
twiz@google.com0f31ca72011-03-18 17:38:11 +0000148 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000149
twiz@google.com0f31ca72011-03-18 17:38:11 +0000150 GrGLuint testFBO;
twiz@google.com59a190b2011-03-14 21:23:01 +0000151 GR_GL(GenFramebuffers(1, &testFBO));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000152 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000153 GrGLuint testRTTex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000154 GR_GL(GenTextures(1, &testRTTex));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000155 GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex));
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000156 // some implementations require texture to be mip-map complete before
157 // FBO with level 0 bound as color attachment will be framebuffer complete.
twiz@google.com0f31ca72011-03-18 17:38:11 +0000158 GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
159 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h,
160 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL));
161 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000162 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
twiz@google.com0f31ca72011-03-18 17:38:11 +0000163 GR_GL_TEXTURE_2D, testRTTex, 0));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000164 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000165 GR_GL(DeleteFramebuffers(1, &testFBO));
reed@google.comac10a2d2010-12-22 21:39:39 +0000166 GR_GL(DeleteTextures(1, &testRTTex));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000167
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000168 GR_GL(ActiveTexture(savedTexUnit));
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000169 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO));
bsalomon@google.com316f99232011-01-13 21:28:12 +0000170
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000171 return status == GR_GL_FRAMEBUFFER_COMPLETE;
reed@google.comac10a2d2010-12-22 21:39:39 +0000172}
173
reed@google.comac10a2d2010-12-22 21:39:39 +0000174GrGpuGL::GrGpuGL() {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000175
reed@google.comeeeb5a02010-12-23 15:12:59 +0000176 if (gPrintStartupSpew) {
177 GrPrintf("------------------------- create GrGpuGL %p --------------\n",
178 this);
twiz@google.com59a190b2011-03-14 21:23:01 +0000179 GrPrintf("------ VENDOR %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000180 GrGLGetGLInterface()->fGetString(GR_GL_VENDOR));
twiz@google.com59a190b2011-03-14 21:23:01 +0000181 GrPrintf("------ RENDERER %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000182 GrGLGetGLInterface()->fGetString(GR_GL_RENDERER));
twiz@google.com59a190b2011-03-14 21:23:01 +0000183 GrPrintf("------ VERSION %s\n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000184 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
twiz@google.com59a190b2011-03-14 21:23:01 +0000185 GrPrintf("------ EXTENSIONS\n %s \n",
twiz@google.com0f31ca72011-03-18 17:38:11 +0000186 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000187 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000188
189 GrGLClearErr();
190
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000191 resetDirtyFlags();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000192
twiz@google.com0f31ca72011-03-18 17:38:11 +0000193 GrGLint maxTextureUnits;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000194 // check FS and fixed-function texture unit limits
195 // we only use textures in the fragment stage currently.
196 // checks are > to make sure we have a spare unit.
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000197 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) {
198 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
199 GrAssert(maxTextureUnits > kNumStages);
200 }
201 if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) {
202 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits);
203 GrAssert(maxTextureUnits > kNumStages);
204 }
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000205 if (GR_GL_SUPPORT_ES2) {
206 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
207 &fMaxFragmentUniformVectors);
208 } else if (GR_GL_SUPPORT_DESKTOP) {
209 GrGLint max;
210 GR_GL_GetIntegerv(GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
211 fMaxFragmentUniformVectors = max / 4;
212 } else {
213 fMaxFragmentUniformVectors = 16;
214 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000215
reed@google.comac10a2d2010-12-22 21:39:39 +0000216 ////////////////////////////////////////////////////////////////////////////
217 // Check for supported features.
218
219 int major, minor;
220 gl_version(&major, &minor);
221
twiz@google.com0f31ca72011-03-18 17:38:11 +0000222 GrGLint numFormats;
223 GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
224 GrAutoSTMalloc<10, GrGLint> formats(numFormats);
225 GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
reed@google.comac10a2d2010-12-22 21:39:39 +0000226 for (int i = 0; i < numFormats; ++i) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000227 if (formats[i] == GR_GL_PALETTE8_RGBA8) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000228 f8bitPaletteSupport = true;
229 break;
230 }
231 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000232
233 if (gPrintStartupSpew) {
234 GrPrintf("Palette8 support: %s\n", (f8bitPaletteSupport ? "YES" : "NO"));
235 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000236
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000237 GR_STATIC_ASSERT(0 == kNone_GrAALevel);
238 GR_STATIC_ASSERT(1 == kLow_GrAALevel);
239 GR_STATIC_ASSERT(2 == kMed_GrAALevel);
240 GR_STATIC_ASSERT(3 == kHigh_GrAALevel);
reed@google.comac10a2d2010-12-22 21:39:39 +0000241
242 memset(fAASamples, 0, sizeof(fAASamples));
243 fMSFBOType = kNone_MSFBO;
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000244 if (GR_GL_SUPPORT_ES) {
245 if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000246 // chrome's extension is equivalent to the EXT msaa
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000247 // and fbo_blit extensions.
248 fMSFBOType = kDesktopEXT_MSFBO;
249 } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
250 fMSFBOType = kAppleES_MSFBO;
251 }
252 } else {
253 GrAssert(GR_GL_SUPPORT_DESKTOP);
254 if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) {
255 fMSFBOType = kDesktopARB_MSFBO;
256 } else if (has_gl_extension("GL_EXT_framebuffer_multisample") &&
257 has_gl_extension("GL_EXT_framebuffer_blit")) {
258 fMSFBOType = kDesktopEXT_MSFBO;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000259 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000260 }
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +0000261 if (gPrintStartupSpew) {
262 switch (fMSFBOType) {
263 case kNone_MSFBO:
264 GrPrintf("MSAA Support: NONE\n");
265 break;
266 case kDesktopARB_MSFBO:
267 GrPrintf("MSAA Support: DESKTOP ARB.\n");
268 break;
269 case kDesktopEXT_MSFBO:
270 GrPrintf("MSAA Support: DESKTOP EXT.\n");
271 break;
272 case kAppleES_MSFBO:
273 GrPrintf("MSAA Support: APPLE ES.\n");
274 break;
reed@google.comeeeb5a02010-12-23 15:12:59 +0000275 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000276 }
277
278 if (kNone_MSFBO != fMSFBOType) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000279 GrGLint maxSamples;
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000280 GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples);
reed@google.comac10a2d2010-12-22 21:39:39 +0000281 if (maxSamples > 1 ) {
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000282 fAASamples[kNone_GrAALevel] = 0;
283 fAASamples[kLow_GrAALevel] = GrMax(2,
284 GrFixedFloorToInt((GR_FixedHalf) *
285 maxSamples));
286 fAASamples[kMed_GrAALevel] = GrMax(2,
287 GrFixedFloorToInt(((GR_Fixed1*3)/4) *
288 maxSamples));
289 fAASamples[kHigh_GrAALevel] = maxSamples;
reed@google.comac10a2d2010-12-22 21:39:39 +0000290 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000291 if (gPrintStartupSpew) {
292 GrPrintf("\tMax Samples: %d\n", maxSamples);
293 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000294 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +0000295 fFSAASupport = fAASamples[kHigh_GrAALevel] > 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000296
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000297 if (GR_GL_SUPPORT_DESKTOP) {
298 fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) ||
299 has_gl_extension("GL_EXT_stencil_wrap");
300 } else {
301 fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap");
302 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000303 if (gPrintStartupSpew) {
304 GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO"));
305 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000306
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000307 if (GR_GL_SUPPORT_DESKTOP) {
308 // we could also look for GL_ATI_separate_stencil extension or
309 // GL_EXT_stencil_two_side but they use different function signatures
310 // than GL2.0+ (and than each other).
311 fTwoSidedStencilSupport = (major >= 2);
312 // supported on GL 1.4 and higher or by extension
313 fStencilWrapOpsSupport = (major > 1) ||
314 ((1 == major) && (minor >= 4)) ||
315 has_gl_extension("GL_EXT_stencil_wrap");
316 } else {
317 // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be
318 // an ES1 extension.
319 fTwoSidedStencilSupport = (major >= 2);
320 // stencil wrap support is in ES2, ES1 requires extension.
321 fStencilWrapOpsSupport = (major > 1) ||
322 has_gl_extension("GL_OES_stencil_wrap");
323 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000324 if (gPrintStartupSpew) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000325 GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n",
326 (fTwoSidedStencilSupport ? "YES" : "NO"),
327 (fStencilWrapOpsSupport ? "YES" : "NO"));
reed@google.comeeeb5a02010-12-23 15:12:59 +0000328 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000329
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000330 if (GR_GL_SUPPORT_DESKTOP) {
331 fRGBA8Renderbuffer = true;
332 } else {
333 fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8");
334 }
reed@google.comeeeb5a02010-12-23 15:12:59 +0000335 if (gPrintStartupSpew) {
336 GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO"));
337 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000338
339
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000340 if (GR_GL_SUPPORT_ES) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000341 if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000342 GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888"));
343 }
344 }
345
346 if (GR_GL_SUPPORT_DESKTOP) {
347 fBufferLockSupport = true; // we require VBO support and the desktop VBO
348 // extension includes glMapBuffer.
349 } else {
350 fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
351 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000352
reed@google.comeeeb5a02010-12-23 15:12:59 +0000353 if (gPrintStartupSpew) {
354 GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
355 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000356
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000357 if (GR_GL_SUPPORT_DESKTOP) {
358 if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) {
359 fNPOTTextureTileSupport = true;
360 fNPOTTextureSupport = true;
361 } else {
362 fNPOTTextureTileSupport = false;
363 fNPOTTextureSupport = false;
364 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000365 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000366 if (major >= 2) {
367 fNPOTTextureSupport = true;
368 fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot");
369 } else {
370 fNPOTTextureSupport =
371 has_gl_extension("GL_APPLE_texture_2D_limited_npot");
372 fNPOTTextureTileSupport = false;
373 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000374 }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000375
bsalomon@google.com205d4602011-04-25 12:43:45 +0000376 fAALineSupport = GR_GL_SUPPORT_DESKTOP;
377
reed@google.comac10a2d2010-12-22 21:39:39 +0000378 ////////////////////////////////////////////////////////////////////////////
379 // Experiments to determine limitations that can't be queried. TODO: Make
380 // these a preprocess that generate some compile time constants.
381
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000382 // sanity check to make sure we can at least create an FBO from a POT texture
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000383
twiz@google.com59a190b2011-03-14 21:23:01 +0000384 bool simpleFBOSuccess = fbo_test(128, 128);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000385 if (gPrintStartupSpew) {
386 if (!simpleFBOSuccess) {
387 GrPrintf("FBO Sanity Test: FAILED\n");
388 } else {
389 GrPrintf("FBO Sanity Test: PASSED\n");
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +0000390 }
391 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000392 GrAssert(simpleFBOSuccess);
reed@google.comac20fb92011-01-12 17:14:53 +0000393
reed@google.comac10a2d2010-12-22 21:39:39 +0000394 /* Experimentation has found that some GLs that support NPOT textures
395 do not support FBOs with a NPOT texture. They report "unsupported" FBO
396 status. I don't know how to explicitly query for this. Do an
397 experiment. Note they may support NPOT with a renderbuffer but not a
398 texture. Presumably, the implementation bloats the renderbuffer
399 internally to the next POT.
400 */
bsalomon@google.com0748f212011-02-01 22:56:16 +0000401 bool fNPOTRenderTargetSupport = false;
402 if (fNPOTTextureSupport) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000403 fNPOTRenderTargetSupport = fbo_test(200, 200);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000404 }
bsalomon@google.com18908aa2011-02-07 14:51:55 +0000405
bsalomon@google.com0748f212011-02-01 22:56:16 +0000406 if (gPrintStartupSpew) {
407 if (fNPOTTextureSupport) {
408 GrPrintf("NPOT textures supported\n");
409 if (fNPOTTextureTileSupport) {
410 GrPrintf("NPOT texture tiling supported\n");
411 } else {
412 GrPrintf("NPOT texture tiling NOT supported\n");
413 }
414 if (fNPOTRenderTargetSupport) {
415 GrPrintf("NPOT render targets supported\n");
416 } else {
417 GrPrintf("NPOT render targets NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000418 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000419 } else {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000420 GrPrintf("NPOT textures NOT supported\n");
reed@google.comeeeb5a02010-12-23 15:12:59 +0000421 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000422 }
423
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000424 GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension);
425
reed@google.comac10a2d2010-12-22 21:39:39 +0000426 /* The iPhone 4 has a restriction that for an FBO with texture color
427 attachment with height <= 8 then the width must be <= height. Here
428 we look for such a limitation.
429 */
430 fMinRenderTargetHeight = GR_INVAL_GLINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000431 GrGLint maxRenderSize;
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000432 GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize);
bsalomon@google.com7aaee002011-04-11 19:54:04 +0000433 // fbo_test creates FBOs with texture bound to the color attachment
434 maxRenderSize = GrMin(maxRenderSize, fMaxTextureDimension);
reed@google.comac10a2d2010-12-22 21:39:39 +0000435
reed@google.comeeeb5a02010-12-23 15:12:59 +0000436 if (gPrintStartupSpew) {
437 GrPrintf("Small height FBO texture experiments\n");
438 }
bsalomon@google.com0748f212011-02-01 22:56:16 +0000439
twiz@google.com0f31ca72011-03-18 17:38:11 +0000440 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
441 GrGLuint w = maxRenderSize;
442 GrGLuint h = i;
twiz@google.com59a190b2011-03-14 21:23:01 +0000443 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000444 if (gPrintStartupSpew) {
445 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
446 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000447 fMinRenderTargetHeight = i;
448 break;
449 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000450 if (gPrintStartupSpew) {
451 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
452 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000453 }
454 }
455 GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
456
reed@google.comeeeb5a02010-12-23 15:12:59 +0000457 if (gPrintStartupSpew) {
458 GrPrintf("Small width FBO texture experiments\n");
459 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000460 fMinRenderTargetWidth = GR_MAX_GLUINT;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000461 for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
462 GrGLuint w = i;
463 GrGLuint h = maxRenderSize;
twiz@google.com59a190b2011-03-14 21:23:01 +0000464 if (fbo_test(w, h)) {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000465 if (gPrintStartupSpew) {
466 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
467 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000468 fMinRenderTargetWidth = i;
469 break;
470 } else {
reed@google.comeeeb5a02010-12-23 15:12:59 +0000471 if (gPrintStartupSpew) {
472 GrPrintf("\t[%d, %d]: FAILED\n", w, h);
473 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000474 }
475 }
476 GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
reed@google.comac10a2d2010-12-22 21:39:39 +0000477}
478
479GrGpuGL::~GrGpuGL() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000480}
481
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000482void GrGpuGL::resetContext() {
483 // We detect cases when blending is effectively off
reed@google.comac10a2d2010-12-22 21:39:39 +0000484 fHWBlendDisabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000485 GR_GL(Enable(GR_GL_BLEND));
reed@google.comac10a2d2010-12-22 21:39:39 +0000486
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000487 // we don't use the zb at all
twiz@google.com0f31ca72011-03-18 17:38:11 +0000488 GR_GL(Disable(GR_GL_DEPTH_TEST));
489 GR_GL(DepthMask(GR_GL_FALSE));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000490
twiz@google.com0f31ca72011-03-18 17:38:11 +0000491 GR_GL(Disable(GR_GL_CULL_FACE));
492 GR_GL(FrontFace(GR_GL_CCW));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000493 fHWDrawState.fDrawFace = kBoth_DrawFace;
reed@google.comac10a2d2010-12-22 21:39:39 +0000494
twiz@google.com0f31ca72011-03-18 17:38:11 +0000495 GR_GL(Disable(GR_GL_DITHER));
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000496 if (GR_GL_SUPPORT_DESKTOP) {
497 GR_GL(Disable(GR_GL_LINE_SMOOTH));
498 GR_GL(Disable(GR_GL_POINT_SMOOTH));
499 GR_GL(Disable(GR_GL_MULTISAMPLE));
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000500 fHWAAState.fMSAAEnabled = false;
501 fHWAAState.fSmoothLineEnabled = false;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000502 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000503
twiz@google.com0f31ca72011-03-18 17:38:11 +0000504 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000505 fHWDrawState.fFlagBits = 0;
506
reed@google.comac10a2d2010-12-22 21:39:39 +0000507 // we only ever use lines in hairline mode
508 GR_GL(LineWidth(1));
509
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000510 // invalid
511 fActiveTextureUnitIdx = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000512
reed@google.comac10a2d2010-12-22 21:39:39 +0000513 // illegal values
bsalomon@google.comffca4002011-02-22 20:34:01 +0000514 fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
515 fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
bsalomon@google.com080773c2011-03-15 19:09:25 +0000516
517 fHWDrawState.fBlendConstant = 0x00000000;
518 GR_GL(BlendColor(0,0,0,0));
519
reed@google.comac10a2d2010-12-22 21:39:39 +0000520 fHWDrawState.fColor = GrColor_ILLEGAL;
bsalomon@google.com316f99232011-01-13 21:28:12 +0000521
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000522 fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000523
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000524 for (int s = 0; s < kNumStages; ++s) {
525 fHWDrawState.fTextures[s] = NULL;
526 fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
527 -GR_ScalarMax,
528 true);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000529
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000530 fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000531 }
bsalomon@google.com316f99232011-01-13 21:28:12 +0000532
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000533 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000534 fHWBounds.fScissorEnabled = false;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000535 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000536 fHWBounds.fViewportRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000537
bsalomon@google.comd302f142011-03-03 13:54:13 +0000538 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +0000539 fHWStencilClip = false;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000540 fClipState.fClipIsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000541
542 fHWGeometryState.fIndexBuffer = NULL;
543 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000544
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +0000545 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000546
twiz@google.com0f31ca72011-03-18 17:38:11 +0000547 GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
reed@google.comac10a2d2010-12-22 21:39:39 +0000548 fHWDrawState.fRenderTarget = NULL;
549}
550
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000551GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) {
552
553 bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType ||
554 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
555 bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType ||
556 kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType;
557
558 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
559 if (isRenderTarget) {
560 rtIDs.fRTFBOID = desc.fPlatformRenderTarget;
561 if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
562 if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) {
563 rtIDs.fTexFBOID = desc.fPlatformResolveDestination;
564 } else {
565 GrAssert(!isTexture); // this should have been filtered by GrContext
566 rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
567 }
568 } else {
569 rtIDs.fTexFBOID = desc.fPlatformRenderTarget;
570 }
571 // we don't know what the RB ids are without glGets and we don't care
572 // since we aren't responsible for deleting them.
573 rtIDs.fStencilRenderbufferID = 0;
574 rtIDs.fMSColorRenderbufferID = 0;
575
576 rtIDs.fOwnIDs = false;
577 } else {
578 rtIDs.reset();
579 }
580
581 if (isTexture) {
582 GrGLTexture::GLTextureDesc texDesc;
583 GrGLenum dontCare;
584 if (!canBeTexture(desc.fConfig, &dontCare,
585 &texDesc.fUploadFormat,
586 &texDesc.fUploadType)) {
587 return NULL;
588 }
589
590 GrGLTexture::TexParams params;
591
592 texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth;
593 texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight;
594
595 texDesc.fFormat = texDesc.fFormat;
596 texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
597 texDesc.fStencilBits = desc.fStencilBits;
598 texDesc.fTextureID = desc.fPlatformTexture;
599 texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig);
600 texDesc.fOwnsID = false;
601
602 params.invalidate(); // rather than do glGets.
603
604 return new GrGLTexture(this, texDesc, rtIDs, params);
605 } else {
606 GrGLIRect viewport;
607 viewport.fLeft = 0;
608 viewport.fBottom = 0;
609 viewport.fWidth = desc.fWidth;
610 viewport.fHeight = desc.fHeight;
611
612 return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits,
613 kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags,
614 viewport, NULL);
615 }
616}
617
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000618GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget(
reed@google.comac10a2d2010-12-22 21:39:39 +0000619 intptr_t platformRenderTarget,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000620 int stencilBits,
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000621 bool isMultisampled,
bsalomon@google.comd302f142011-03-03 13:54:13 +0000622 int width,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000623 int height) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000624 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
625 rtIDs.fStencilRenderbufferID = 0;
626 rtIDs.fMSColorRenderbufferID = 0;
627 rtIDs.fTexFBOID = 0;
628 rtIDs.fOwnIDs = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000629 GrGLIRect viewport;
reed@google.comac10a2d2010-12-22 21:39:39 +0000630
631 // viewport is in GL coords (top >= bottom)
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000632 viewport.fLeft = 0;
633 viewport.fBottom = 0;
634 viewport.fWidth = width;
635 viewport.fHeight = height;
reed@google.comac10a2d2010-12-22 21:39:39 +0000636
twiz@google.com0f31ca72011-03-18 17:38:11 +0000637 rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget;
638 rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +0000639
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000640 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
641 isMultisampled, viewport, NULL);
reed@google.comac10a2d2010-12-22 21:39:39 +0000642}
643
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000644GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000645
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000646 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000647
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000648 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000649 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
650 rtIDs.fMSColorRenderbufferID = 0;
651 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000652
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000653 GrGLIRect viewport;
654 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000655 GrGLuint stencilBits;
656 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000657
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000658 GrGLint samples;
659 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
660
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000661 rtIDs.fOwnIDs = false;
662
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000663 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
664 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000665}
666
bsalomon@google.com5782d712011-01-21 21:03:59 +0000667///////////////////////////////////////////////////////////////////////////////
668
twiz@google.com0f31ca72011-03-18 17:38:11 +0000669static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000670
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000671struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000672 GrGLenum fEnum;
673 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000674 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000675};
676
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000677const StencilFormat* GrGLStencilFormats() {
678 // defines stencil formats from more to less preferred
679 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000680 {GR_GL_STENCIL_INDEX8, 8, false},
681 {GR_GL_STENCIL_INDEX16, 16, false},
682 {GR_GL_DEPTH24_STENCIL8, 8, true },
683 {GR_GL_STENCIL_INDEX4, 4, false},
684 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
685 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
686 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000687 };
688
689 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000690 {GR_GL_STENCIL_INDEX8, 8, false},
691 {GR_GL_DEPTH24_STENCIL8, 8, true },
692 {GR_GL_STENCIL_INDEX4, 4, false},
693 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000694 };
695
696 if (GR_GL_SUPPORT_DESKTOP) {
697 return desktopStencilFormats;
698 } else {
699 return esStencilFormats;
700 }
701}
702
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000703// good to set a break-point here to know when createTexture fails
704static GrTexture* return_null_texture() {
705// GrAssert(!"null texture");
706 return NULL;
707}
708
709#if GR_DEBUG
710static size_t as_size_t(int x) {
711 return x;
712}
713#endif
714
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000715GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000716 const void* srcData,
717 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000718
719#if GR_COLLECT_STATS
720 ++fStats.fTextureCreateCnt;
721#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000722
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000723 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000724
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000725 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000726 GR_GL_NEAREST,
727 GR_GL_CLAMP_TO_EDGE,
728 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000729 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000730
reed@google.comac10a2d2010-12-22 21:39:39 +0000731 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000732 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000733
734 glDesc.fContentWidth = desc.fWidth;
735 glDesc.fContentHeight = desc.fHeight;
736 glDesc.fAllocWidth = desc.fWidth;
737 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000738 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000739 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000740 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000741
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000742 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000743 if (!canBeTexture(desc.fFormat,
744 &internalFormat,
745 &glDesc.fUploadFormat,
746 &glDesc.fUploadType)) {
747 return return_null_texture();
748 }
749
750 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000751 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000752 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000753 GrPrintf("AA RT requested but not supported on this platform.");
754 }
755
756 GR_GL(GenTextures(1, &glDesc.fTextureID));
757 if (!glDesc.fTextureID) {
758 return return_null_texture();
759 }
760
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000761 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000762
reed@google.com5e762232011-04-04 18:15:49 +0000763 // in case we need a temporary, trimmed copy of the src pixels
764 GrAutoSMalloc<128 * 128> trimStorage;
765
reed@google.comac10a2d2010-12-22 21:39:39 +0000766 /*
767 * check if our srcData has extra bytes past each row. If so, we need
768 * to trim those off here, since GL doesn't let us pass the rowBytes as
769 * a parameter to glTexImage2D
770 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000771 if (GR_GL_SUPPORT_DESKTOP) {
772 if (srcData) {
773 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
774 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000775 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000776 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000777 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
778 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000779 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000780 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000781 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000782 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000783 for (uint32_t y = 0; y < desc.fHeight; y++) {
784 memcpy(dst, src, trimRowBytes);
785 src += rowBytes;
786 dst += trimRowBytes;
787 }
788 // now point srcData to our trimmed version
789 srcData = trimStorage.get();
790 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000791 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000792
reed@google.comac10a2d2010-12-22 21:39:39 +0000793 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000794 if (!this->npotRenderTargetSupport()) {
795 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
796 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
797 }
798
reed@google.comac10a2d2010-12-22 21:39:39 +0000799 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
800 glDesc.fAllocWidth);
801 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
802 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000803 } else if (!this->npotTextureSupport()) {
804 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
805 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000806 }
807
twiz@google.com0f31ca72011-03-18 17:38:11 +0000808 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
809 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
810 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000811 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000812 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
813 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000814 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000815 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
816 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000817 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000818 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
819 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000820 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000821
twiz@google.com0f31ca72011-03-18 17:38:11 +0000822 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000823 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000824 supports8BitPalette()) {
825 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
826 GrAssert(desc.fWidth == glDesc.fAllocWidth);
827 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000828 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000829 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000830 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000831 glDesc.fAllocWidth, glDesc.fAllocHeight,
832 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000833 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000834 } else {
835 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
836 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000837 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000838 glDesc.fAllocWidth, glDesc.fAllocHeight,
839 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000840 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000841 desc.fHeight, glDesc.fUploadFormat,
842 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000843 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000844
845 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
846 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
847 uint32_t maxTexels = extraW * extraH;
848 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
849 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
850
851 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
852
853 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
854 if (extraH) {
855 uint8_t* lastRowStart = (uint8_t*) srcData +
856 (desc.fHeight - 1) * rowSize;
857 uint8_t* extraRowStart = (uint8_t*)texels.get();
858
859 for (uint32_t i = 0; i < extraH; ++i) {
860 memcpy(extraRowStart, lastRowStart, rowSize);
861 extraRowStart += rowSize;
862 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000863 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000864 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
865 texels.get()));
866 }
867 if (extraW) {
868 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
869 uint8_t* extraTexel = (uint8_t*)texels.get();
870 for (uint32_t j = 0; j < desc.fHeight; ++j) {
871 for (uint32_t i = 0; i < extraW; ++i) {
872 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
873 extraTexel += glDesc.fUploadByteCount;
874 }
875 edgeTexel += rowSize;
876 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000877 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000878 desc.fHeight, glDesc.fUploadFormat,
879 glDesc.fUploadType, texels.get()));
880 }
881 if (extraW && extraH) {
882 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
883 - glDesc.fUploadByteCount;
884 uint8_t* extraTexel = (uint8_t*)texels.get();
885 for (uint32_t i = 0; i < extraW*extraH; ++i) {
886 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
887 extraTexel += glDesc.fUploadByteCount;
888 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000889 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000890 extraW, extraH, glDesc.fUploadFormat,
891 glDesc.fUploadType, texels.get()));
892 }
893
894 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000895 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000896 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
897 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000898 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000899 }
900 }
901
902 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
903
904 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
905 rtIDs.fStencilRenderbufferID = 0;
906 rtIDs.fMSColorRenderbufferID = 0;
907 rtIDs.fRTFBOID = 0;
908 rtIDs.fTexFBOID = 0;
909 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000910 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000911
912 if (renderTarget) {
913#if GR_COLLECT_STATS
914 ++fStats.fRenderTargetCreateCnt;
915#endif
916 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000917 GrGLenum status;
918 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000919
920 // If need have both RT flag and srcData we have
921 // to invert the data before uploading because FBO
922 // will be rendered bottom up
923 GrAssert(NULL == srcData);
924 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
925
twiz@google.com59a190b2011-03-14 21:23:01 +0000926 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000927 GrAssert(rtIDs.fTexFBOID);
928
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000929 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000930 // to one and then resolve to the texture bound to the other.
931 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000932 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000933 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000934 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000935 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
936 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000937 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000938 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000939 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
940 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000941 return return_null_texture();
942 }
943 } else {
944 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
945 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000946 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000947 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000948 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000949 }
950
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000951 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000952 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000953 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000954 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000955
twiz@google.com0f31ca72011-03-18 17:38:11 +0000956 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000957
958 const StencilFormat* stencilFormats = GrGLStencilFormats();
959 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000960 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000961 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000962 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000963 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000964 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000965 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000966 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000967 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000968 glDesc.fAllocWidth,
969 glDesc.fAllocHeight));
970 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000971 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000972 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000973 glDesc.fAllocWidth,
974 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000975 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000976 err = GrGLGetGLInterface()->fGetError();
977 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000978 continue;
979 }
980 }
981 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
982 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000983 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000984 rtIDs.fMSColorRenderbufferID));
985 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000986 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000987 samples,
988 msColorRenderbufferFormat,
989 glDesc.fAllocWidth,
990 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000991 err = GrGLGetGLInterface()->fGetError();
992 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000993 continue;
994 }
995 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000996 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000997
998#if GR_COLLECT_STATS
999 ++fStats.fRenderTargetChngCnt;
1000#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +00001001 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
1002 GR_GL_COLOR_ATTACHMENT0,
1003 GR_GL_TEXTURE_2D,
1004 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +00001005 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001006 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1007 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001008 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1009 status, desc.fWidth, desc.fHeight);
1010 continue;
1011 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001012 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001013 #if GR_COLLECT_STATS
1014 ++fStats.fRenderTargetChngCnt;
1015 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001016 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1017 GR_GL_COLOR_ATTACHMENT0,
1018 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001019 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001020
1021 }
1022 if (rtIDs.fStencilRenderbufferID) {
1023 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001024 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1025 GR_GL_STENCIL_ATTACHMENT,
1026 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001027 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001028 // if it is a packed format bind to depth also, otherwise
1029 // we may get an unsupported fbo completeness result
1030 if (stencilFormats[i].fPacked) {
1031 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1032 GR_GL_DEPTH_ATTACHMENT,
1033 GR_GL_RENDERBUFFER,
1034 rtIDs.fStencilRenderbufferID));
1035 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001036 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001037 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001038
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001039 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001040 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1041 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001042 // undo the depth bind
1043 if (rtIDs.fStencilRenderbufferID &&
1044 stencilFormats[i].fPacked) {
1045 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1046 GR_GL_DEPTH_ATTACHMENT,
1047 GR_GL_RENDERBUFFER,
1048 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001049 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001050 continue;
1051 }
1052 // we're successful!
1053 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001054 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001055 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001056 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001057 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001058 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001059 }
1060 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001061 break;
1062 }
1063 if (failed) {
1064 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001065 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001066 }
1067 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001068 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001069 }
1070 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001071 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001072 }
1073 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001074 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001075 }
1076 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1077 return return_null_texture();
1078 }
1079 }
1080#ifdef TRACE_TEXTURE_CREATION
1081 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1082 tex->fTextureID, width, height, tex->fUploadByteCount);
1083#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001084 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001085
1086 if (0 != rtIDs.fTexFBOID) {
1087 GrRenderTarget* rt = tex->asRenderTarget();
1088 // We've messed with FBO state but may not have set the correct viewport
1089 // so just dirty the rendertarget state to force a resend.
1090 fHWDrawState.fRenderTarget = NULL;
1091
1092 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001093 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1095 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001096 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001097 fCurrDrawState.fRenderTarget = rtSave;
1098 }
1099 }
1100 return tex;
1101}
1102
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001103GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001104 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001105 GR_GL(GenBuffers(1, &id));
1106 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001107 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001108 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001109 GrGLClearErr();
1110 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001111 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1112 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1113 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001114 GR_GL(DeleteBuffers(1, &id));
1115 // deleting bound buffer does implicit bind to 0
1116 fHWGeometryState.fVertexBuffer = NULL;
1117 return NULL;
1118 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001119 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001120 size, dynamic);
1121 fHWGeometryState.fVertexBuffer = vertexBuffer;
1122 return vertexBuffer;
1123 }
1124 return NULL;
1125}
1126
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001127GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001128 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001129 GR_GL(GenBuffers(1, &id));
1130 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001131 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001132 GrGLClearErr();
1133 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001134 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1135 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1136 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001137 GR_GL(DeleteBuffers(1, &id));
1138 // deleting bound buffer does implicit bind to 0
1139 fHWGeometryState.fIndexBuffer = NULL;
1140 return NULL;
1141 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001142 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001143 size, dynamic);
1144 fHWGeometryState.fIndexBuffer = indexBuffer;
1145 return indexBuffer;
1146 }
1147 return NULL;
1148}
1149
reed@google.comac10a2d2010-12-22 21:39:39 +00001150void GrGpuGL::flushScissor(const GrIRect* rect) {
1151 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001152 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001153 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001154
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001155 GrGLIRect scissor;
1156 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001157 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001158 rect->width(), rect->height());
1159 if (scissor.contains(vp)) {
1160 rect = NULL;
1161 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001162 }
1163
1164 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001165 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001166 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001167 fHWBounds.fScissorRect = scissor;
1168 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001169 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001170 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001171 fHWBounds.fScissorEnabled = true;
1172 }
1173 } else {
1174 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001175 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001176 fHWBounds.fScissorEnabled = false;
1177 }
1178 }
1179}
1180
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001181void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001182 if (NULL == fCurrDrawState.fRenderTarget) {
1183 return;
1184 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001185 GrIRect r;
1186 if (NULL != rect) {
1187 // flushScissor expects rect to be clipped to the target.
1188 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001189 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1190 fCurrDrawState.fRenderTarget->height());
1191 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001192 rect = &r;
1193 } else {
1194 return;
1195 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001196 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001197 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001198 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001199 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001200 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001201 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1202 GrColorUnpackG(color)/255.f,
1203 GrColorUnpackB(color)/255.f,
1204 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001205 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001206}
1207
bsalomon@google.com398109c2011-04-14 18:40:27 +00001208void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001209 if (NULL == fCurrDrawState.fRenderTarget) {
1210 return;
1211 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001212
1213 this->flushRenderTarget(&GrIRect::EmptyIRect());
1214
reed@google.comac10a2d2010-12-22 21:39:39 +00001215 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001216 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001217 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001218 }
1219 GR_GL(StencilMask(mask));
1220 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001221 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001222 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001223}
1224
bsalomon@google.com398109c2011-04-14 18:40:27 +00001225void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001226 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001227#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001228 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001229 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001230 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001231#else
1232 // we could just clear the clip bit but when we go through
1233 // angle a partial stencil mask will cause clears to be
1234 // turned into draws. Our contract on GrDrawTarget says that
1235 // changing the clip between stencil passes may or may not
1236 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001237 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001238#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001239 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001240 flushScissor(&rect);
1241 GR_GL(StencilMask(clipStencilMask));
1242 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001243 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001244 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001245}
1246
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001247void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001248 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001249}
1250
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001251bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1252 int left, int top, int width, int height,
1253 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001254 GrGLenum internalFormat; // we don't use this for glReadPixels
1255 GrGLenum format;
1256 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001257 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1258 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001259 }
1260 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1261 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1262 switch (tgt->getResolveType()) {
1263 case GrGLRenderTarget::kCantResolve_ResolveType:
1264 return false;
1265 case GrGLRenderTarget::kAutoResolves_ResolveType:
1266 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1267 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001268 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001269 break;
1270 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001271 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001272 // we don't track the state of the READ FBO ID.
1273 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1274 break;
1275 default:
1276 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001277 }
1278
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001279 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001280
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001281 // the read rect is viewport-relative
1282 GrGLIRect readRect;
1283 readRect.setRelativeTo(glvp, left, top, width, height);
1284 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001285 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001286 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001287
1288 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1289 // API presents top-to-bottom
1290 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001291 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001292 GrAutoMalloc rowStorage(stride);
1293 void* tmp = rowStorage.get();
1294
1295 const int halfY = height >> 1;
1296 char* top = reinterpret_cast<char*>(buffer);
1297 char* bottom = top + (height - 1) * stride;
1298 for (int y = 0; y < halfY; y++) {
1299 memcpy(tmp, top, stride);
1300 memcpy(top, bottom, stride);
1301 memcpy(bottom, tmp, stride);
1302 top += stride;
1303 bottom -= stride;
1304 }
1305 }
1306 return true;
1307}
1308
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001309void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001310
1311 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1312
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001313 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001314 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001315 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001316 #if GR_COLLECT_STATS
1317 ++fStats.fRenderTargetChngCnt;
1318 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001319 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001320 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1321 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001322 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1323 }
1324 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001325 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001326 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001327 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001328 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001329 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001330 fHWBounds.fViewportRect = vp;
1331 }
1332 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001333 if (NULL == bound || !bound->isEmpty()) {
1334 rt->flagAsNeedingResolve(bound);
1335 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001336}
1337
twiz@google.com0f31ca72011-03-18 17:38:11 +00001338GrGLenum gPrimitiveType2GLMode[] = {
1339 GR_GL_TRIANGLES,
1340 GR_GL_TRIANGLE_STRIP,
1341 GR_GL_TRIANGLE_FAN,
1342 GR_GL_POINTS,
1343 GR_GL_LINES,
1344 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001345};
1346
bsalomon@google.comd302f142011-03-03 13:54:13 +00001347#define SWAP_PER_DRAW 0
1348
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001349#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001350 #if GR_MAC_BUILD
1351 #include <AGL/agl.h>
1352 #elif GR_WIN32_BUILD
1353 void SwapBuf() {
1354 DWORD procID = GetCurrentProcessId();
1355 HWND hwnd = GetTopWindow(GetDesktopWindow());
1356 while(hwnd) {
1357 DWORD wndProcID = 0;
1358 GetWindowThreadProcessId(hwnd, &wndProcID);
1359 if(wndProcID == procID) {
1360 SwapBuffers(GetDC(hwnd));
1361 }
1362 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1363 }
1364 }
1365 #endif
1366#endif
1367
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001368void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1369 uint32_t startVertex,
1370 uint32_t startIndex,
1371 uint32_t vertexCount,
1372 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001373 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1374
twiz@google.com0f31ca72011-03-18 17:38:11 +00001375 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001376
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001377 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1378 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1379
1380 // our setupGeometry better have adjusted this to zero since
1381 // DrawElements always draws from the begining of the arrays for idx 0.
1382 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001383
1384 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001385 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001386#if SWAP_PER_DRAW
1387 glFlush();
1388 #if GR_MAC_BUILD
1389 aglSwapBuffers(aglGetCurrentContext());
1390 int set_a_break_pt_here = 9;
1391 aglSwapBuffers(aglGetCurrentContext());
1392 #elif GR_WIN32_BUILD
1393 SwapBuf();
1394 int set_a_break_pt_here = 9;
1395 SwapBuf();
1396 #endif
1397#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001398}
1399
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001400void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1401 uint32_t startVertex,
1402 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001403 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1404
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001405 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1406
1407 // our setupGeometry better have adjusted this to zero.
1408 // DrawElements doesn't take an offset so we always adjus the startVertex.
1409 GrAssert(0 == startVertex);
1410
1411 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1412 // account for startVertex in the DrawElements case. So we always
1413 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001414 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001415#if SWAP_PER_DRAW
1416 glFlush();
1417 #if GR_MAC_BUILD
1418 aglSwapBuffers(aglGetCurrentContext());
1419 int set_a_break_pt_here = 9;
1420 aglSwapBuffers(aglGetCurrentContext());
1421 #elif GR_WIN32_BUILD
1422 SwapBuf();
1423 int set_a_break_pt_here = 9;
1424 SwapBuf();
1425 #endif
1426#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001427}
1428
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001429void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001430
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001431 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001432 GrAssert(kNone_MSFBO != fMSFBOType);
1433 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001434 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001435 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001436 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001437 rt->textureFBOID()));
1438 #if GR_COLLECT_STATS
1439 ++fStats.fRenderTargetChngCnt;
1440 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001441 // make sure we go through flushRenderTarget() since we've modified
1442 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001443 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001444 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001445 const GrIRect dirtyRect = rt->getResolveRect();
1446 GrGLIRect r;
1447 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1448 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001449
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001450 if (kAppleES_MSFBO == fMSFBOType) {
1451 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001452 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001453 GR_GL(Scissor(r.fLeft, r.fBottom,
1454 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001455 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001456 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001457 fHWBounds.fScissorEnabled = true;
1458 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001459 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001460 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001461 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1462 flushScissor(NULL);
1463 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001464 int right = r.fLeft + r.fWidth;
1465 int top = r.fBottom + r.fHeight;
1466 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1467 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001468 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001469 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001470 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001471 }
1472}
1473
twiz@google.com0f31ca72011-03-18 17:38:11 +00001474static const GrGLenum grToGLStencilFunc[] = {
1475 GR_GL_ALWAYS, // kAlways_StencilFunc
1476 GR_GL_NEVER, // kNever_StencilFunc
1477 GR_GL_GREATER, // kGreater_StencilFunc
1478 GR_GL_GEQUAL, // kGEqual_StencilFunc
1479 GR_GL_LESS, // kLess_StencilFunc
1480 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1481 GR_GL_EQUAL, // kEqual_StencilFunc,
1482 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001483};
1484GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1485GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1486GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1487GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1488GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1489GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1490GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1491GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1492GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1493
twiz@google.com0f31ca72011-03-18 17:38:11 +00001494static const GrGLenum grToGLStencilOp[] = {
1495 GR_GL_KEEP, // kKeep_StencilOp
1496 GR_GL_REPLACE, // kReplace_StencilOp
1497 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1498 GR_GL_INCR, // kIncClamp_StencilOp
1499 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1500 GR_GL_DECR, // kDecClamp_StencilOp
1501 GR_GL_ZERO, // kZero_StencilOp
1502 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001503};
1504GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1505GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1506GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1507GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1508GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1509GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1510GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1511GR_STATIC_ASSERT(6 == kZero_StencilOp);
1512GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1513
reed@google.comac10a2d2010-12-22 21:39:39 +00001514void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001515 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001516
1517 // use stencil for clipping if clipping is enabled and the clip
1518 // has been written into the stencil.
1519 bool stencilClip = fClipState.fClipInStencil &&
1520 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001521 bool stencilChange = fHWStencilClip != stencilClip ||
1522 fHWDrawState.fStencilSettings != *settings ||
1523 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1524 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001525
1526 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001527
bsalomon@google.comd302f142011-03-03 13:54:13 +00001528 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1529 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001530
bsalomon@google.comd302f142011-03-03 13:54:13 +00001531 if (settings->isDisabled()) {
1532 if (stencilClip) {
1533 settings = &gClipStencilSettings;
1534 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001535 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001536
1537 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001538 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001539 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001540 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001541 #if GR_DEBUG
1542 if (!fStencilWrapOpsSupport) {
1543 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1544 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1545 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1546 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1547 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1548 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1549 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1550 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1551 }
1552 #endif
1553 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1554 GrAssert(stencilBits ||
1555 (GrStencilSettings::gDisabled ==
1556 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001557 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1558 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001559
1560 unsigned int frontRef = settings->fFrontFuncRef;
1561 unsigned int frontMask = settings->fFrontFuncMask;
1562 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001563 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001564
1565 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1566
1567 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1568 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1569 } else {
1570 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1571
1572 ConvertStencilFuncAndMask(settings->fFrontFunc,
1573 stencilClip,
1574 clipStencilMask,
1575 userStencilMask,
1576 &frontRef,
1577 &frontMask);
1578 frontWriteMask &= userStencilMask;
1579 }
1580 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001581 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001582 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001583 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001584 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001585 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001586 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001587 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001588 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001589 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001590
1591 unsigned int backRef = settings->fBackFuncRef;
1592 unsigned int backMask = settings->fBackFuncMask;
1593 unsigned int backWriteMask = settings->fBackWriteMask;
1594
1595
1596 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1597 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1598 backFunc = grToGLStencilFunc[settings->fBackFunc];
1599 } else {
1600 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1601 ConvertStencilFuncAndMask(settings->fBackFunc,
1602 stencilClip,
1603 clipStencilMask,
1604 userStencilMask,
1605 &backRef,
1606 &backMask);
1607 backWriteMask &= userStencilMask;
1608 }
1609
twiz@google.com0f31ca72011-03-18 17:38:11 +00001610 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1611 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1612 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1613 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1614 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001615 grToGLStencilOp[settings->fFrontPassOp],
1616 grToGLStencilOp[settings->fFrontPassOp]));
1617
twiz@google.com0f31ca72011-03-18 17:38:11 +00001618 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001619 grToGLStencilOp[settings->fBackPassOp],
1620 grToGLStencilOp[settings->fBackPassOp]));
1621 } else {
1622 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1623 GR_GL(StencilMask(frontWriteMask));
1624 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1625 grToGLStencilOp[settings->fFrontPassOp],
1626 grToGLStencilOp[settings->fFrontPassOp]));
1627 }
1628 }
1629 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001630 fHWStencilClip = stencilClip;
1631 }
1632}
1633
bsalomon@google.com0650e812011-04-08 18:07:53 +00001634bool GrGpuGL::useSmoothLines() {
1635 // there is a conflict between using smooth lines and our use of
1636 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1637 // but not in a premul-alpha way. So we only use them when our alpha
1638 // is 0xff.
1639
1640 // TODO: write a smarter line frag shader.
1641
1642 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1643 canDisableBlend();
1644}
1645
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001646void GrGpuGL::flushAAState(GrPrimitiveType type) {
1647 if (GR_GL_SUPPORT_DESKTOP) {
1648 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1649 // smooth lines.
1650
1651 // we prefer smooth lines over multisampled lines
1652 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001653 if (GrIsPrimTypeLines(type)) {
1654 bool smooth = useSmoothLines();
1655 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001656 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1657 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001658 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001659 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1660 fHWAAState.fSmoothLineEnabled = false;
1661 }
1662 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1663 fHWAAState.fMSAAEnabled) {
1664 GR_GL(Disable(GR_GL_MULTISAMPLE));
1665 fHWAAState.fMSAAEnabled = false;
1666 }
1667 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1668 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1669 fHWAAState.fMSAAEnabled) {
1670 if (fHWAAState.fMSAAEnabled) {
1671 GR_GL(Disable(GR_GL_MULTISAMPLE));
1672 fHWAAState.fMSAAEnabled = false;
1673 } else {
1674 GR_GL(Enable(GR_GL_MULTISAMPLE));
1675 fHWAAState.fMSAAEnabled = true;
1676 }
1677 }
1678 }
1679}
1680
bsalomon@google.com0650e812011-04-08 18:07:53 +00001681void GrGpuGL::flushBlend(GrPrimitiveType type) {
1682 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) {
1705 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1706 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1707 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1708 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1709 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1710 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1711 }
1712 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1713 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1714 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);
1816 this->flushBlend(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001817
reed@google.comac10a2d2010-12-22 21:39:39 +00001818 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1819 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1820 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001821 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001822 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001823 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001824 }
1825 }
1826
bsalomon@google.comd302f142011-03-03 13:54:13 +00001827 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1828 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001829 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001830 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001831 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001832 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001833 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001834 }
1835 GR_GL(ColorMask(mask, mask, mask, mask));
1836 }
1837
bsalomon@google.comd302f142011-03-03 13:54:13 +00001838 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1839 switch (fCurrDrawState.fDrawFace) {
1840 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001841 GR_GL(Enable(GR_GL_CULL_FACE));
1842 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001843 break;
1844 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001845 GR_GL(Enable(GR_GL_CULL_FACE));
1846 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001847 break;
1848 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001849 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001850 break;
1851 default:
1852 GrCrash("Unknown draw face.");
1853 }
1854 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1855 }
1856
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001857#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001858 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001859 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001860 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001861 NULL == fCurrDrawState.fRenderTarget ||
1862 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001863 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001864 fCurrDrawState.fRenderTarget);
1865 }
1866#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001867
reed@google.comac10a2d2010-12-22 21:39:39 +00001868 flushStencil();
1869
bsalomon@google.comd302f142011-03-03 13:54:13 +00001870 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001871 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001872 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001873}
1874
1875void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001876 if (fHWGeometryState.fVertexBuffer != buffer) {
1877 fHWGeometryState.fArrayPtrsDirty = true;
1878 fHWGeometryState.fVertexBuffer = buffer;
1879 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001880}
1881
1882void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001883 if (fHWGeometryState.fVertexBuffer == buffer) {
1884 // deleting bound buffer does implied bind to 0
1885 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001886 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001887 }
1888}
1889
1890void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1891 fGeometrySrc.fIndexBuffer = buffer;
1892}
1893
1894void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001895 if (fHWGeometryState.fIndexBuffer == buffer) {
1896 // deleting bound buffer does implied bind to 0
1897 fHWGeometryState.fIndexBuffer = NULL;
1898 }
1899}
1900
reed@google.comac10a2d2010-12-22 21:39:39 +00001901void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1902 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001903 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001904 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001905 }
1906 if (fHWDrawState.fRenderTarget == renderTarget) {
1907 fHWDrawState.fRenderTarget = NULL;
1908 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001909}
1910
1911void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001912 for (int s = 0; s < kNumStages; ++s) {
1913 if (fCurrDrawState.fTextures[s] == texture) {
1914 fCurrDrawState.fTextures[s] = NULL;
1915 }
1916 if (fHWDrawState.fTextures[s] == texture) {
1917 // deleting bound texture does implied bind to 0
1918 fHWDrawState.fTextures[s] = NULL;
1919 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001920 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001921}
1922
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001923bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001924 GrGLenum* internalFormat,
1925 GrGLenum* format,
1926 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001927 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001928 case kRGBA_8888_GrPixelConfig:
1929 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001930 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001931 if (GR_GL_SUPPORT_ES) {
1932 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1933 // format for a BGRA is BGRA not RGBA (as on desktop)
1934 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1935 } else {
1936 *internalFormat = GR_GL_RGBA;
1937 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001938 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001939 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001940 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001941 *format = GR_GL_RGB;
1942 *internalFormat = GR_GL_RGB;
1943 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001944 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001945 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001946 *format = GR_GL_RGBA;
1947 *internalFormat = GR_GL_RGBA;
1948 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001949 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001950 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001951 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001952 *format = GR_GL_PALETTE8_RGBA8;
1953 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001954 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001955 } else {
1956 return false;
1957 }
1958 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001959 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001960 *format = GR_GL_ALPHA;
1961 *internalFormat = GR_GL_ALPHA;
1962 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001963 break;
1964 default:
1965 return false;
1966 }
1967 return true;
1968}
1969
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001970void GrGpuGL::setTextureUnit(int unit) {
1971 GrAssert(unit >= 0 && unit < kNumStages);
1972 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001973 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001974 fActiveTextureUnitIdx = unit;
1975 }
1976}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001977
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001978void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001979 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1980 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001981 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1982 }
1983}
1984
reed@google.comac10a2d2010-12-22 21:39:39 +00001985/* On ES the internalFormat and format must match for TexImage and we use
1986 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1987 decide the internalFormat. However, on ES internalFormat for
1988 RenderBufferStorage* has to be a specific format (not a base format like
1989 GL_RGBA).
1990 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001991bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001992 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001993 case kRGBA_8888_GrPixelConfig:
1994 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001995 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001996 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001997 return true;
1998 } else {
1999 return false;
2000 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002001 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00002002 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
2003 // with FBO extension desktop GL has
2004 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00002005 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00002006 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002007 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00002008 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00002009 return true;
2010 default:
2011 return false;
2012 }
2013}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002014
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00002015void GrGpuGL::resetDirtyFlags() {
2016 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
2017}
2018
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002019void GrGpuGL::setBuffers(bool indexed,
2020 int* extraVertexOffset,
2021 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002022
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002023 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002024
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002025 GrGLVertexBuffer* vbuf;
2026 switch (fGeometrySrc.fVertexSrc) {
2027 case kBuffer_GeometrySrcType:
2028 *extraVertexOffset = 0;
2029 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2030 break;
2031 case kArray_GeometrySrcType:
2032 case kReserved_GeometrySrcType:
2033 finalizeReservedVertices();
2034 *extraVertexOffset = fCurrPoolStartVertex;
2035 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2036 break;
2037 default:
2038 vbuf = NULL; // suppress warning
2039 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002040 }
2041
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002042 GrAssert(NULL != vbuf);
2043 GrAssert(!vbuf->isLocked());
2044 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002045 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002046 fHWGeometryState.fArrayPtrsDirty = true;
2047 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002048 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002049
2050 if (indexed) {
2051 GrAssert(NULL != extraIndexOffset);
2052
2053 GrGLIndexBuffer* ibuf;
2054 switch (fGeometrySrc.fIndexSrc) {
2055 case kBuffer_GeometrySrcType:
2056 *extraIndexOffset = 0;
2057 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2058 break;
2059 case kArray_GeometrySrcType:
2060 case kReserved_GeometrySrcType:
2061 finalizeReservedIndices();
2062 *extraIndexOffset = fCurrPoolStartIndex;
2063 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2064 break;
2065 default:
2066 ibuf = NULL; // suppress warning
2067 GrCrash("Unknown geometry src type!");
2068 }
2069
2070 GrAssert(NULL != ibuf);
2071 GrAssert(!ibuf->isLocked());
2072 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002073 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002074 fHWGeometryState.fIndexBuffer = ibuf;
2075 }
2076 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002077}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002078
2079int GrGpuGL::getMaxEdges() const {
2080 // FIXME: This is a pessimistic estimate based on how many other things
2081 // want to add uniforms. This should be centralized somewhere.
2082 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2083}