blob: 2e3563ec708b1f66a351864f3485713c2883f8b1 [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::onCreateRenderTargetFrom3DApiState() {
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000619
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000620 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000621
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000622 GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000623 rtIDs.fTexFBOID = rtIDs.fRTFBOID;
624 rtIDs.fMSColorRenderbufferID = 0;
625 rtIDs.fStencilRenderbufferID = 0;
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +0000626
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000627 GrGLIRect viewport;
628 viewport.setFromGLViewport();
twiz@google.com0f31ca72011-03-18 17:38:11 +0000629 GrGLuint stencilBits;
630 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000631
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000632 GrGLint samples;
633 GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples);
634
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000635 rtIDs.fOwnIDs = false;
636
bsalomon@google.comf954d8d2011-04-06 17:50:02 +0000637 return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits,
638 (samples > 0), viewport, NULL);
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000639}
640
bsalomon@google.com5782d712011-01-21 21:03:59 +0000641///////////////////////////////////////////////////////////////////////////////
642
twiz@google.com0f31ca72011-03-18 17:38:11 +0000643static const GrGLuint UNKNOWN_BITS = ~0;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000644
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000645struct StencilFormat {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000646 GrGLenum fEnum;
647 GrGLuint fBits;
bsalomon@google.com9283b582011-04-08 19:00:04 +0000648 bool fPacked;
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000649};
650
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000651const StencilFormat* GrGLStencilFormats() {
652 // defines stencil formats from more to less preferred
653 static const StencilFormat desktopStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000654 {GR_GL_STENCIL_INDEX8, 8, false},
655 {GR_GL_STENCIL_INDEX16, 16, false},
656 {GR_GL_DEPTH24_STENCIL8, 8, true },
657 {GR_GL_STENCIL_INDEX4, 4, false},
658 {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false},
659 {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true },
660 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000661 };
662
663 static const StencilFormat esStencilFormats[] = {
bsalomon@google.com9283b582011-04-08 19:00:04 +0000664 {GR_GL_STENCIL_INDEX8, 8, false},
665 {GR_GL_DEPTH24_STENCIL8, 8, true },
666 {GR_GL_STENCIL_INDEX4, 4, false},
667 {0, 0, false}
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000668 };
669
670 if (GR_GL_SUPPORT_DESKTOP) {
671 return desktopStencilFormats;
672 } else {
673 return esStencilFormats;
674 }
675}
676
bsalomon@google.com3f3ffd62011-01-18 17:14:52 +0000677// good to set a break-point here to know when createTexture fails
678static GrTexture* return_null_texture() {
679// GrAssert(!"null texture");
680 return NULL;
681}
682
683#if GR_DEBUG
684static size_t as_size_t(int x) {
685 return x;
686}
687#endif
688
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000689GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000690 const void* srcData,
691 size_t rowBytes) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000692
693#if GR_COLLECT_STATS
694 ++fStats.fTextureCreateCnt;
695#endif
reed@google.com1fcd51e2011-01-05 15:50:27 +0000696
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000697 this->setSpareTextureUnit();
bsalomon@google.com316f99232011-01-13 21:28:12 +0000698
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000699 static const GrGLTexture::TexParams DEFAULT_PARAMS = {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000700 GR_GL_NEAREST,
701 GR_GL_CLAMP_TO_EDGE,
702 GR_GL_CLAMP_TO_EDGE
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000703 };
reed@google.com1fcd51e2011-01-05 15:50:27 +0000704
reed@google.comac10a2d2010-12-22 21:39:39 +0000705 GrGLTexture::GLTextureDesc glDesc;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000706 GrGLenum internalFormat;
reed@google.comac10a2d2010-12-22 21:39:39 +0000707
708 glDesc.fContentWidth = desc.fWidth;
709 glDesc.fContentHeight = desc.fHeight;
710 glDesc.fAllocWidth = desc.fWidth;
711 glDesc.fAllocHeight = desc.fHeight;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +0000712 glDesc.fStencilBits = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +0000713 glDesc.fFormat = desc.fFormat;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +0000714 glDesc.fOwnsID = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000715
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000716 bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
reed@google.comac10a2d2010-12-22 21:39:39 +0000717 if (!canBeTexture(desc.fFormat,
718 &internalFormat,
719 &glDesc.fUploadFormat,
720 &glDesc.fUploadType)) {
721 return return_null_texture();
722 }
723
724 GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000725 GrGLint samples = fAASamples[desc.fAALevel];
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000726 if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000727 GrPrintf("AA RT requested but not supported on this platform.");
728 }
729
730 GR_GL(GenTextures(1, &glDesc.fTextureID));
731 if (!glDesc.fTextureID) {
732 return return_null_texture();
733 }
734
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000735 glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
reed@google.comac10a2d2010-12-22 21:39:39 +0000736
reed@google.com5e762232011-04-04 18:15:49 +0000737 // in case we need a temporary, trimmed copy of the src pixels
738 GrAutoSMalloc<128 * 128> trimStorage;
739
reed@google.comac10a2d2010-12-22 21:39:39 +0000740 /*
741 * check if our srcData has extra bytes past each row. If so, we need
742 * to trim those off here, since GL doesn't let us pass the rowBytes as
743 * a parameter to glTexImage2D
744 */
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000745 if (GR_GL_SUPPORT_DESKTOP) {
746 if (srcData) {
747 GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
748 rowBytes / glDesc.fUploadByteCount));
reed@google.comac10a2d2010-12-22 21:39:39 +0000749 }
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000750 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000751 size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
752 if (srcData && (trimRowBytes < rowBytes)) {
reed@google.com5e762232011-04-04 18:15:49 +0000753 // copy the data into our new storage, skipping the trailing bytes
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000754 size_t trimSize = desc.fHeight * trimRowBytes;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000755 const char* src = (const char*)srcData;
reed@google.com5e762232011-04-04 18:15:49 +0000756 char* dst = (char*)trimStorage.realloc(trimSize);
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000757 for (uint32_t y = 0; y < desc.fHeight; y++) {
758 memcpy(dst, src, trimRowBytes);
759 src += rowBytes;
760 dst += trimRowBytes;
761 }
762 // now point srcData to our trimmed version
763 srcData = trimStorage.get();
764 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000765 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000766
reed@google.comac10a2d2010-12-22 21:39:39 +0000767 if (renderTarget) {
bsalomon@google.com0748f212011-02-01 22:56:16 +0000768 if (!this->npotRenderTargetSupport()) {
769 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
770 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
771 }
772
reed@google.comac10a2d2010-12-22 21:39:39 +0000773 glDesc.fAllocWidth = GrMax<int>(fMinRenderTargetWidth,
774 glDesc.fAllocWidth);
775 glDesc.fAllocHeight = GrMax<int>(fMinRenderTargetHeight,
776 glDesc.fAllocHeight);
bsalomon@google.com0748f212011-02-01 22:56:16 +0000777 } else if (!this->npotTextureSupport()) {
778 glDesc.fAllocWidth = GrNextPow2(desc.fWidth);
779 glDesc.fAllocHeight = GrNextPow2(desc.fHeight);
reed@google.comac10a2d2010-12-22 21:39:39 +0000780 }
781
twiz@google.com0f31ca72011-03-18 17:38:11 +0000782 GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
783 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
784 GR_GL_TEXTURE_MAG_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000785 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000786 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
787 GR_GL_TEXTURE_MIN_FILTER,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000788 DEFAULT_PARAMS.fFilter));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000789 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
790 GR_GL_TEXTURE_WRAP_S,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000791 DEFAULT_PARAMS.fWrapS));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000792 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
793 GR_GL_TEXTURE_WRAP_T,
bsalomon@google.comda96ea02010-12-23 16:53:57 +0000794 DEFAULT_PARAMS.fWrapT));
reed@google.comac10a2d2010-12-22 21:39:39 +0000795
twiz@google.com0f31ca72011-03-18 17:38:11 +0000796 GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount));
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000797 if (kIndex_8_GrPixelConfig == desc.fFormat &&
reed@google.comac10a2d2010-12-22 21:39:39 +0000798 supports8BitPalette()) {
799 // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
800 GrAssert(desc.fWidth == glDesc.fAllocWidth);
801 GrAssert(desc.fHeight == glDesc.fAllocHeight);
twiz@google.com0f31ca72011-03-18 17:38:11 +0000802 GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight +
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000803 kGrColorTableSize;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000804 GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000805 glDesc.fAllocWidth, glDesc.fAllocHeight,
806 0, imageSize, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000807 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000808 } else {
809 if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth ||
810 glDesc.fAllocHeight != desc.fHeight)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000811 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
reed@google.comac10a2d2010-12-22 21:39:39 +0000812 glDesc.fAllocWidth, glDesc.fAllocHeight,
813 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000814 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000815 desc.fHeight, glDesc.fUploadFormat,
816 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000817 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000818
819 uint32_t extraW = glDesc.fAllocWidth - desc.fWidth;
820 uint32_t extraH = glDesc.fAllocHeight - desc.fHeight;
821 uint32_t maxTexels = extraW * extraH;
822 maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
823 maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
824
825 GrAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
826
827 uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
828 if (extraH) {
829 uint8_t* lastRowStart = (uint8_t*) srcData +
830 (desc.fHeight - 1) * rowSize;
831 uint8_t* extraRowStart = (uint8_t*)texels.get();
832
833 for (uint32_t i = 0; i < extraH; ++i) {
834 memcpy(extraRowStart, lastRowStart, rowSize);
835 extraRowStart += rowSize;
836 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000837 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000838 extraH, glDesc.fUploadFormat, glDesc.fUploadType,
839 texels.get()));
840 }
841 if (extraW) {
842 uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
843 uint8_t* extraTexel = (uint8_t*)texels.get();
844 for (uint32_t j = 0; j < desc.fHeight; ++j) {
845 for (uint32_t i = 0; i < extraW; ++i) {
846 memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
847 extraTexel += glDesc.fUploadByteCount;
848 }
849 edgeTexel += rowSize;
850 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000851 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
reed@google.comac10a2d2010-12-22 21:39:39 +0000852 desc.fHeight, glDesc.fUploadFormat,
853 glDesc.fUploadType, texels.get()));
854 }
855 if (extraW && extraH) {
856 uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
857 - glDesc.fUploadByteCount;
858 uint8_t* extraTexel = (uint8_t*)texels.get();
859 for (uint32_t i = 0; i < extraW*extraH; ++i) {
860 memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount);
861 extraTexel += glDesc.fUploadByteCount;
862 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000863 GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
reed@google.comac10a2d2010-12-22 21:39:39 +0000864 extraW, extraH, glDesc.fUploadFormat,
865 glDesc.fUploadType, texels.get()));
866 }
867
868 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +0000869 GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth,
reed@google.comac10a2d2010-12-22 21:39:39 +0000870 glDesc.fAllocHeight, 0, glDesc.fUploadFormat,
871 glDesc.fUploadType, srcData));
bsalomon@google.comf987d1b2011-04-04 17:13:52 +0000872 GrGLRestoreResetRowLength();
reed@google.comac10a2d2010-12-22 21:39:39 +0000873 }
874 }
875
876 glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
877
878 GrGLRenderTarget::GLRenderTargetIDs rtIDs;
879 rtIDs.fStencilRenderbufferID = 0;
880 rtIDs.fMSColorRenderbufferID = 0;
881 rtIDs.fRTFBOID = 0;
882 rtIDs.fTexFBOID = 0;
883 rtIDs.fOwnIDs = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000884 GrGLenum msColorRenderbufferFormat = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000885
886 if (renderTarget) {
887#if GR_COLLECT_STATS
888 ++fStats.fRenderTargetCreateCnt;
889#endif
890 bool failed = true;
twiz@google.com0f31ca72011-03-18 17:38:11 +0000891 GrGLenum status;
892 GrGLint err;
reed@google.comac10a2d2010-12-22 21:39:39 +0000893
894 // If need have both RT flag and srcData we have
895 // to invert the data before uploading because FBO
896 // will be rendered bottom up
897 GrAssert(NULL == srcData);
898 glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
899
twiz@google.com59a190b2011-03-14 21:23:01 +0000900 GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000901 GrAssert(rtIDs.fTexFBOID);
902
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000903 // If we are using multisampling and we will create two FBOS We render
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000904 // to one and then resolve to the texture bound to the other.
905 if (samples > 1 && kNone_MSFBO != fMSFBOType) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000906 GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000907 GrAssert(0 != rtIDs.fRTFBOID);
twiz@google.com59a190b2011-03-14 21:23:01 +0000908 GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000909 GrAssert(0 != rtIDs.fMSColorRenderbufferID);
910 if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000911 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000912 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
twiz@google.com59a190b2011-03-14 21:23:01 +0000913 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
914 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000915 return return_null_texture();
916 }
917 } else {
918 rtIDs.fRTFBOID = rtIDs.fTexFBOID;
919 }
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000920 if (!(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000921 GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000922 GrAssert(0 != rtIDs.fStencilRenderbufferID);
reed@google.comac10a2d2010-12-22 21:39:39 +0000923 }
924
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000925 // someone suggested that some systems might require
bsalomon@google.com316f99232011-01-13 21:28:12 +0000926 // unbinding the texture before we call FramebufferTexture2D
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000927 // (seems unlikely)
twiz@google.com0f31ca72011-03-18 17:38:11 +0000928 GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000929
twiz@google.com0f31ca72011-03-18 17:38:11 +0000930 err = ~GR_GL_NO_ERROR;
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000931
932 const StencilFormat* stencilFormats = GrGLStencilFormats();
933 for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000934 if (rtIDs.fStencilRenderbufferID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000935 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000936 rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000937 if (samples > 1) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000938 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000939 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000940 samples,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000941 stencilFormats[i].fEnum,
reed@google.comac10a2d2010-12-22 21:39:39 +0000942 glDesc.fAllocWidth,
943 glDesc.fAllocHeight));
944 } else {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000945 GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER,
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000946 stencilFormats[i].fEnum,
twiz@google.com59a190b2011-03-14 21:23:01 +0000947 glDesc.fAllocWidth,
948 glDesc.fAllocHeight));
reed@google.comac10a2d2010-12-22 21:39:39 +0000949 }
twiz@google.com0f31ca72011-03-18 17:38:11 +0000950 err = GrGLGetGLInterface()->fGetError();
951 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000952 continue;
953 }
954 }
955 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
956 GrAssert(samples > 1);
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000957 GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000958 rtIDs.fMSColorRenderbufferID));
959 GR_GL_NO_ERR(RenderbufferStorageMultisample(
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000960 GR_GL_RENDERBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +0000961 samples,
962 msColorRenderbufferFormat,
963 glDesc.fAllocWidth,
964 glDesc.fAllocHeight));
twiz@google.com0f31ca72011-03-18 17:38:11 +0000965 err = GrGLGetGLInterface()->fGetError();
966 if (err != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000967 continue;
968 }
969 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000970 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000971
972#if GR_COLLECT_STATS
973 ++fStats.fRenderTargetChngCnt;
974#endif
bsalomon@google.comd1e433532011-03-21 21:38:40 +0000975 GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
976 GR_GL_COLOR_ATTACHMENT0,
977 GR_GL_TEXTURE_2D,
978 glDesc.fTextureID, 0));
reed@google.comac10a2d2010-12-22 21:39:39 +0000979 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000980 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
981 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000982 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
983 status, desc.fWidth, desc.fHeight);
984 continue;
985 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000986 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000987 #if GR_COLLECT_STATS
988 ++fStats.fRenderTargetChngCnt;
989 #endif
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000990 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
991 GR_GL_COLOR_ATTACHMENT0,
992 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +0000993 rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +0000994
995 }
996 if (rtIDs.fStencilRenderbufferID) {
997 // bind the stencil to rt fbo if present, othewise the tex fbo
bsalomon@google.comc312bf92011-03-21 21:10:33 +0000998 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
999 GR_GL_STENCIL_ATTACHMENT,
1000 GR_GL_RENDERBUFFER,
twiz@google.com59a190b2011-03-14 21:23:01 +00001001 rtIDs.fStencilRenderbufferID));
bsalomon@google.com9283b582011-04-08 19:00:04 +00001002 // if it is a packed format bind to depth also, otherwise
1003 // we may get an unsupported fbo completeness result
1004 if (stencilFormats[i].fPacked) {
1005 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1006 GR_GL_DEPTH_ATTACHMENT,
1007 GR_GL_RENDERBUFFER,
1008 rtIDs.fStencilRenderbufferID));
1009 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001010 }
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001011 status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001012
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001013 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001014 GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
1015 status, desc.fWidth, desc.fHeight);
bsalomon@google.com9283b582011-04-08 19:00:04 +00001016 // undo the depth bind
1017 if (rtIDs.fStencilRenderbufferID &&
1018 stencilFormats[i].fPacked) {
1019 GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
1020 GR_GL_DEPTH_ATTACHMENT,
1021 GR_GL_RENDERBUFFER,
1022 0));
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001023 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001024 continue;
1025 }
1026 // we're successful!
1027 failed = false;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001028 if (rtIDs.fStencilRenderbufferID) {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001029 if (UNKNOWN_BITS == stencilFormats[i].fBits) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001030 GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001031 } else {
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001032 glDesc.fStencilBits = stencilFormats[i].fBits;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001033 }
1034 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001035 break;
1036 }
1037 if (failed) {
1038 if (rtIDs.fStencilRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001039 GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001040 }
1041 if (rtIDs.fMSColorRenderbufferID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001042 GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001043 }
1044 if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001045 GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001046 }
1047 if (rtIDs.fTexFBOID) {
twiz@google.com59a190b2011-03-14 21:23:01 +00001048 GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
reed@google.comac10a2d2010-12-22 21:39:39 +00001049 }
1050 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
1051 return return_null_texture();
1052 }
1053 }
1054#ifdef TRACE_TEXTURE_CREATION
1055 GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n",
1056 tex->fTextureID, width, height, tex->fUploadByteCount);
1057#endif
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001058 GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS);
reed@google.comac10a2d2010-12-22 21:39:39 +00001059
1060 if (0 != rtIDs.fTexFBOID) {
1061 GrRenderTarget* rt = tex->asRenderTarget();
1062 // We've messed with FBO state but may not have set the correct viewport
1063 // so just dirty the rendertarget state to force a resend.
1064 fHWDrawState.fRenderTarget = NULL;
1065
1066 // clear the new stencil buffer if we have one
bsalomon@google.comfea37b52011-04-25 15:51:06 +00001067 if (!(desc.fFlags & kNoStencil_GrTextureFlagBit)) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001068 GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget;
1069 fCurrDrawState.fRenderTarget = rt;
bsalomon@google.com398109c2011-04-14 18:40:27 +00001070 this->clearStencil(0, ~0);
reed@google.comac10a2d2010-12-22 21:39:39 +00001071 fCurrDrawState.fRenderTarget = rtSave;
1072 }
1073 }
1074 return tex;
1075}
1076
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001077GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001078 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001079 GR_GL(GenBuffers(1, &id));
1080 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001081 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001082 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001083 GrGLClearErr();
1084 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001085 GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL,
1086 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1087 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001088 GR_GL(DeleteBuffers(1, &id));
1089 // deleting bound buffer does implicit bind to 0
1090 fHWGeometryState.fVertexBuffer = NULL;
1091 return NULL;
1092 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001093 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001094 size, dynamic);
1095 fHWGeometryState.fVertexBuffer = vertexBuffer;
1096 return vertexBuffer;
1097 }
1098 return NULL;
1099}
1100
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001101GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001102 GrGLuint id;
reed@google.comac10a2d2010-12-22 21:39:39 +00001103 GR_GL(GenBuffers(1, &id));
1104 if (id) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001105 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
reed@google.comac10a2d2010-12-22 21:39:39 +00001106 GrGLClearErr();
1107 // make sure driver can allocate memory for this buffer
twiz@google.com0f31ca72011-03-18 17:38:11 +00001108 GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL,
1109 dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
1110 if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001111 GR_GL(DeleteBuffers(1, &id));
1112 // deleting bound buffer does implicit bind to 0
1113 fHWGeometryState.fIndexBuffer = NULL;
1114 return NULL;
1115 }
bsalomon@google.com8fe72472011-03-30 21:26:44 +00001116 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id,
reed@google.comac10a2d2010-12-22 21:39:39 +00001117 size, dynamic);
1118 fHWGeometryState.fIndexBuffer = indexBuffer;
1119 return indexBuffer;
1120 }
1121 return NULL;
1122}
1123
reed@google.comac10a2d2010-12-22 21:39:39 +00001124void GrGpuGL::flushScissor(const GrIRect* rect) {
1125 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001126 const GrGLIRect& vp =
bsalomon@google.comd302f142011-03-03 13:54:13 +00001127 ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001128
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001129 GrGLIRect scissor;
1130 if (NULL != rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001131 scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001132 rect->width(), rect->height());
1133 if (scissor.contains(vp)) {
1134 rect = NULL;
1135 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001136 }
1137
1138 if (NULL != rect) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001139 if (fHWBounds.fScissorRect != scissor) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001140 scissor.pushToGLScissor();
reed@google.comac10a2d2010-12-22 21:39:39 +00001141 fHWBounds.fScissorRect = scissor;
1142 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001143 if (!fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001144 GR_GL(Enable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001145 fHWBounds.fScissorEnabled = true;
1146 }
1147 } else {
1148 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001149 GR_GL(Disable(GR_GL_SCISSOR_TEST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001150 fHWBounds.fScissorEnabled = false;
1151 }
1152 }
1153}
1154
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001155void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001156 if (NULL == fCurrDrawState.fRenderTarget) {
1157 return;
1158 }
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001159 GrIRect r;
1160 if (NULL != rect) {
1161 // flushScissor expects rect to be clipped to the target.
1162 r = *rect;
reed@google.com20efde72011-05-09 17:00:02 +00001163 GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
1164 fCurrDrawState.fRenderTarget->height());
1165 if (r.intersect(rtRect)) {
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001166 rect = &r;
1167 } else {
1168 return;
1169 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001170 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001171 this->flushRenderTarget(rect);
bsalomon@google.com6aa25c32011-04-27 19:55:29 +00001172 this->flushScissor(rect);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001173 GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001174 fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
reed@google.comac10a2d2010-12-22 21:39:39 +00001175 GR_GL(ClearColor(GrColorUnpackR(color)/255.f,
1176 GrColorUnpackG(color)/255.f,
1177 GrColorUnpackB(color)/255.f,
1178 GrColorUnpackA(color)/255.f));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001179 GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT));
reed@google.comac10a2d2010-12-22 21:39:39 +00001180}
1181
bsalomon@google.com398109c2011-04-14 18:40:27 +00001182void GrGpuGL::clearStencil(uint32_t value, uint32_t mask) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001183 if (NULL == fCurrDrawState.fRenderTarget) {
1184 return;
1185 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001186
1187 this->flushRenderTarget(&GrIRect::EmptyIRect());
1188
reed@google.comac10a2d2010-12-22 21:39:39 +00001189 if (fHWBounds.fScissorEnabled) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001190 GR_GL(Disable(GR_GL_SCISSOR_TEST));
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001191 fHWBounds.fScissorEnabled = false;
reed@google.comac10a2d2010-12-22 21:39:39 +00001192 }
1193 GR_GL(StencilMask(mask));
1194 GR_GL(ClearStencil(value));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001195 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001196 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001197}
1198
bsalomon@google.com398109c2011-04-14 18:40:27 +00001199void GrGpuGL::clearStencilClip(const GrIRect& rect) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001200 GrAssert(NULL != fCurrDrawState.fRenderTarget);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001201#if 0
twiz@google.com0f31ca72011-03-18 17:38:11 +00001202 GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits();
reed@google.comac10a2d2010-12-22 21:39:39 +00001203 GrAssert(stencilBitCount > 0);
twiz@google.com0f31ca72011-03-18 17:38:11 +00001204 GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001205#else
1206 // we could just clear the clip bit but when we go through
1207 // angle a partial stencil mask will cause clears to be
1208 // turned into draws. Our contract on GrDrawTarget says that
1209 // changing the clip between stencil passes may or may not
1210 // zero the client's clip bits. So we just clear the whole thing.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001211 static const GrGLint clipStencilMask = ~0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00001212#endif
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001213 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.comd302f142011-03-03 13:54:13 +00001214 flushScissor(&rect);
1215 GR_GL(StencilMask(clipStencilMask));
1216 GR_GL(ClearStencil(0));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001217 GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001218 fHWDrawState.fStencilSettings.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001219}
1220
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001221void GrGpuGL::onForceRenderTargetFlush() {
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001222 this->flushRenderTarget(&GrIRect::EmptyIRect());
reed@google.comac10a2d2010-12-22 21:39:39 +00001223}
1224
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001225bool GrGpuGL::onReadPixels(GrRenderTarget* target,
1226 int left, int top, int width, int height,
1227 GrPixelConfig config, void* buffer) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001228 GrGLenum internalFormat; // we don't use this for glReadPixels
1229 GrGLenum format;
1230 GrGLenum type;
reed@google.comac10a2d2010-12-22 21:39:39 +00001231 if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
1232 return false;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001233 }
1234 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
1235 GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
1236 switch (tgt->getResolveType()) {
1237 case GrGLRenderTarget::kCantResolve_ResolveType:
1238 return false;
1239 case GrGLRenderTarget::kAutoResolves_ResolveType:
1240 autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
1241 fCurrDrawState.fRenderTarget = target;
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001242 this->flushRenderTarget(&GrIRect::EmptyIRect());
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001243 break;
1244 case GrGLRenderTarget::kCanResolve_ResolveType:
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001245 this->resolveRenderTarget(tgt);
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001246 // we don't track the state of the READ FBO ID.
1247 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
1248 break;
1249 default:
1250 GrCrash("Unknown resolve type");
reed@google.comac10a2d2010-12-22 21:39:39 +00001251 }
1252
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001253 const GrGLIRect& glvp = tgt->getViewport();
bsalomon@google.comd302f142011-03-03 13:54:13 +00001254
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001255 // the read rect is viewport-relative
1256 GrGLIRect readRect;
1257 readRect.setRelativeTo(glvp, left, top, width, height);
1258 GR_GL(ReadPixels(readRect.fLeft, readRect.fBottom,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001259 readRect.fWidth, readRect.fHeight,
bsalomon@google.com316f99232011-01-13 21:28:12 +00001260 format, type, buffer));
reed@google.comac10a2d2010-12-22 21:39:39 +00001261
1262 // now reverse the order of the rows, since GL's are bottom-to-top, but our
1263 // API presents top-to-bottom
1264 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001265 size_t stride = width * GrBytesPerPixel(config);
reed@google.comac10a2d2010-12-22 21:39:39 +00001266 GrAutoMalloc rowStorage(stride);
1267 void* tmp = rowStorage.get();
1268
1269 const int halfY = height >> 1;
1270 char* top = reinterpret_cast<char*>(buffer);
1271 char* bottom = top + (height - 1) * stride;
1272 for (int y = 0; y < halfY; y++) {
1273 memcpy(tmp, top, stride);
1274 memcpy(top, bottom, stride);
1275 memcpy(bottom, tmp, stride);
1276 top += stride;
1277 bottom -= stride;
1278 }
1279 }
1280 return true;
1281}
1282
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001283void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001284
1285 GrAssert(NULL != fCurrDrawState.fRenderTarget);
1286
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001287 GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
reed@google.comac10a2d2010-12-22 21:39:39 +00001288 if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001289 GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
reed@google.comac10a2d2010-12-22 21:39:39 +00001290 #if GR_COLLECT_STATS
1291 ++fStats.fRenderTargetChngCnt;
1292 #endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001293 #if GR_DEBUG
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001294 GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
1295 if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001296 GrPrintf("-- glCheckFramebufferStatus %x\n", status);
1297 }
1298 #endif
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001299 fDirtyFlags.fRenderTargetChanged = true;
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001300 fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001301 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com649a8622011-03-10 14:53:38 +00001302 if (fHWBounds.fViewportRect != vp) {
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001303 vp.pushToGLViewport();
reed@google.comac10a2d2010-12-22 21:39:39 +00001304 fHWBounds.fViewportRect = vp;
1305 }
1306 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001307 if (NULL == bound || !bound->isEmpty()) {
1308 rt->flagAsNeedingResolve(bound);
1309 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001310}
1311
twiz@google.com0f31ca72011-03-18 17:38:11 +00001312GrGLenum gPrimitiveType2GLMode[] = {
1313 GR_GL_TRIANGLES,
1314 GR_GL_TRIANGLE_STRIP,
1315 GR_GL_TRIANGLE_FAN,
1316 GR_GL_POINTS,
1317 GR_GL_LINES,
1318 GR_GL_LINE_STRIP
reed@google.comac10a2d2010-12-22 21:39:39 +00001319};
1320
bsalomon@google.comd302f142011-03-03 13:54:13 +00001321#define SWAP_PER_DRAW 0
1322
bsalomon@google.coma7f84e12011-03-10 14:13:19 +00001323#if SWAP_PER_DRAW
bsalomon@google.comd302f142011-03-03 13:54:13 +00001324 #if GR_MAC_BUILD
1325 #include <AGL/agl.h>
1326 #elif GR_WIN32_BUILD
1327 void SwapBuf() {
1328 DWORD procID = GetCurrentProcessId();
1329 HWND hwnd = GetTopWindow(GetDesktopWindow());
1330 while(hwnd) {
1331 DWORD wndProcID = 0;
1332 GetWindowThreadProcessId(hwnd, &wndProcID);
1333 if(wndProcID == procID) {
1334 SwapBuffers(GetDC(hwnd));
1335 }
1336 hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
1337 }
1338 }
1339 #endif
1340#endif
1341
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001342void GrGpuGL::onDrawIndexed(GrPrimitiveType type,
1343 uint32_t startVertex,
1344 uint32_t startIndex,
1345 uint32_t vertexCount,
1346 uint32_t indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001347 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1348
twiz@google.com0f31ca72011-03-18 17:38:11 +00001349 GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001350
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001351 GrAssert(NULL != fHWGeometryState.fIndexBuffer);
1352 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1353
1354 // our setupGeometry better have adjusted this to zero since
1355 // DrawElements always draws from the begining of the arrays for idx 0.
1356 GrAssert(0 == startVertex);
reed@google.comac10a2d2010-12-22 21:39:39 +00001357
1358 GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001359 GR_GL_UNSIGNED_SHORT, indices));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001360#if SWAP_PER_DRAW
1361 glFlush();
1362 #if GR_MAC_BUILD
1363 aglSwapBuffers(aglGetCurrentContext());
1364 int set_a_break_pt_here = 9;
1365 aglSwapBuffers(aglGetCurrentContext());
1366 #elif GR_WIN32_BUILD
1367 SwapBuf();
1368 int set_a_break_pt_here = 9;
1369 SwapBuf();
1370 #endif
1371#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001372}
1373
bsalomon@google.combcdbbe62011-04-12 15:40:00 +00001374void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type,
1375 uint32_t startVertex,
1376 uint32_t vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001377 GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
1378
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001379 GrAssert(NULL != fHWGeometryState.fVertexBuffer);
1380
1381 // our setupGeometry better have adjusted this to zero.
1382 // DrawElements doesn't take an offset so we always adjus the startVertex.
1383 GrAssert(0 == startVertex);
1384
1385 // pass 0 for parameter first. We have to adjust gl*Pointer() to
1386 // account for startVertex in the DrawElements case. So we always
1387 // rely on setupGeometry to have accounted for startVertex.
reed@google.comac10a2d2010-12-22 21:39:39 +00001388 GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001389#if SWAP_PER_DRAW
1390 glFlush();
1391 #if GR_MAC_BUILD
1392 aglSwapBuffers(aglGetCurrentContext());
1393 int set_a_break_pt_here = 9;
1394 aglSwapBuffers(aglGetCurrentContext());
1395 #elif GR_WIN32_BUILD
1396 SwapBuf();
1397 int set_a_break_pt_here = 9;
1398 SwapBuf();
1399 #endif
1400#endif
reed@google.comac10a2d2010-12-22 21:39:39 +00001401}
1402
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001403void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001404
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001405 if (rt->needsResolve()) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001406 GrAssert(kNone_MSFBO != fMSFBOType);
1407 GrAssert(rt->textureFBOID() != rt->renderFBOID());
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001408 GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001409 rt->renderFBOID()));
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001410 GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER,
reed@google.comac10a2d2010-12-22 21:39:39 +00001411 rt->textureFBOID()));
1412 #if GR_COLLECT_STATS
1413 ++fStats.fRenderTargetChngCnt;
1414 #endif
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001415 // make sure we go through flushRenderTarget() since we've modified
1416 // the bound DRAW FBO ID.
reed@google.comac10a2d2010-12-22 21:39:39 +00001417 fHWDrawState.fRenderTarget = NULL;
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001418 const GrGLIRect& vp = rt->getViewport();
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001419 const GrIRect dirtyRect = rt->getResolveRect();
1420 GrGLIRect r;
1421 r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
1422 dirtyRect.width(), dirtyRect.height());
reed@google.comac10a2d2010-12-22 21:39:39 +00001423
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001424 if (kAppleES_MSFBO == fMSFBOType) {
1425 // Apple's extension uses the scissor as the blit bounds.
twiz@google.com0f31ca72011-03-18 17:38:11 +00001426 GR_GL(Enable(GR_GL_SCISSOR_TEST));
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001427 GR_GL(Scissor(r.fLeft, r.fBottom,
1428 r.fWidth, r.fHeight));
twiz@google.com59a190b2011-03-14 21:23:01 +00001429 GR_GL(ResolveMultisampleFramebuffer());
bsalomon@google.com8895a7a2011-02-18 16:09:55 +00001430 fHWBounds.fScissorRect.invalidate();
reed@google.comac10a2d2010-12-22 21:39:39 +00001431 fHWBounds.fScissorEnabled = true;
1432 } else {
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001433 if (kDesktopARB_MSFBO != fMSFBOType) {
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001434 // this respects the scissor during the blit, so disable it.
bsalomon@google.coma9ecdad2011-03-23 13:50:34 +00001435 GrAssert(kDesktopEXT_MSFBO == fMSFBOType);
1436 flushScissor(NULL);
1437 }
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001438 int right = r.fLeft + r.fWidth;
1439 int top = r.fBottom + r.fHeight;
1440 GR_GL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
1441 r.fLeft, r.fBottom, right, top,
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001442 GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
reed@google.comac10a2d2010-12-22 21:39:39 +00001443 }
bsalomon@google.com5877ffd2011-04-11 17:58:48 +00001444 rt->flagAsResolved();
reed@google.comac10a2d2010-12-22 21:39:39 +00001445 }
1446}
1447
twiz@google.com0f31ca72011-03-18 17:38:11 +00001448static const GrGLenum grToGLStencilFunc[] = {
1449 GR_GL_ALWAYS, // kAlways_StencilFunc
1450 GR_GL_NEVER, // kNever_StencilFunc
1451 GR_GL_GREATER, // kGreater_StencilFunc
1452 GR_GL_GEQUAL, // kGEqual_StencilFunc
1453 GR_GL_LESS, // kLess_StencilFunc
1454 GR_GL_LEQUAL, // kLEqual_StencilFunc,
1455 GR_GL_EQUAL, // kEqual_StencilFunc,
1456 GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
bsalomon@google.comd302f142011-03-03 13:54:13 +00001457};
1458GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount);
1459GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
1460GR_STATIC_ASSERT(1 == kNever_StencilFunc);
1461GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
1462GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
1463GR_STATIC_ASSERT(4 == kLess_StencilFunc);
1464GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
1465GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
1466GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
1467
twiz@google.com0f31ca72011-03-18 17:38:11 +00001468static const GrGLenum grToGLStencilOp[] = {
1469 GR_GL_KEEP, // kKeep_StencilOp
1470 GR_GL_REPLACE, // kReplace_StencilOp
1471 GR_GL_INCR_WRAP, // kIncWrap_StencilOp
1472 GR_GL_INCR, // kIncClamp_StencilOp
1473 GR_GL_DECR_WRAP, // kDecWrap_StencilOp
1474 GR_GL_DECR, // kDecClamp_StencilOp
1475 GR_GL_ZERO, // kZero_StencilOp
1476 GR_GL_INVERT, // kInvert_StencilOp
bsalomon@google.comd302f142011-03-03 13:54:13 +00001477};
1478GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount);
1479GR_STATIC_ASSERT(0 == kKeep_StencilOp);
1480GR_STATIC_ASSERT(1 == kReplace_StencilOp);
1481GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
1482GR_STATIC_ASSERT(3 == kIncClamp_StencilOp);
1483GR_STATIC_ASSERT(4 == kDecWrap_StencilOp);
1484GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
1485GR_STATIC_ASSERT(6 == kZero_StencilOp);
1486GR_STATIC_ASSERT(7 == kInvert_StencilOp);
1487
reed@google.comac10a2d2010-12-22 21:39:39 +00001488void GrGpuGL::flushStencil() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00001489 const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001490
1491 // use stencil for clipping if clipping is enabled and the clip
1492 // has been written into the stencil.
1493 bool stencilClip = fClipState.fClipInStencil &&
1494 (kClip_StateBit & fCurrDrawState.fFlagBits);
bsalomon@google.comd302f142011-03-03 13:54:13 +00001495 bool stencilChange = fHWStencilClip != stencilClip ||
1496 fHWDrawState.fStencilSettings != *settings ||
1497 ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
1498 (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001499
1500 if (stencilChange) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001501
bsalomon@google.comd302f142011-03-03 13:54:13 +00001502 // we can't simultaneously perform stencil-clipping and modify the stencil clip
1503 GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
reed@google.comac10a2d2010-12-22 21:39:39 +00001504
bsalomon@google.comd302f142011-03-03 13:54:13 +00001505 if (settings->isDisabled()) {
1506 if (stencilClip) {
1507 settings = &gClipStencilSettings;
1508 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001509 }
bsalomon@google.comd302f142011-03-03 13:54:13 +00001510
1511 if (settings->isDisabled()) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001512 GR_GL(Disable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001513 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001514 GR_GL(Enable(GR_GL_STENCIL_TEST));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001515 #if GR_DEBUG
1516 if (!fStencilWrapOpsSupport) {
1517 GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp);
1518 GrAssert(settings->fFrontPassOp != kDecWrap_StencilOp);
1519 GrAssert(settings->fFrontFailOp != kIncWrap_StencilOp);
1520 GrAssert(settings->fBackFailOp != kDecWrap_StencilOp);
1521 GrAssert(settings->fBackPassOp != kIncWrap_StencilOp);
1522 GrAssert(settings->fBackPassOp != kDecWrap_StencilOp);
1523 GrAssert(settings->fBackFailOp != kIncWrap_StencilOp);
1524 GrAssert(settings->fFrontFailOp != kDecWrap_StencilOp);
1525 }
1526 #endif
1527 int stencilBits = fCurrDrawState.fRenderTarget->stencilBits();
1528 GrAssert(stencilBits ||
1529 (GrStencilSettings::gDisabled ==
1530 fCurrDrawState.fStencilSettings));
twiz@google.com0f31ca72011-03-18 17:38:11 +00001531 GrGLuint clipStencilMask = 1 << (stencilBits - 1);
1532 GrGLuint userStencilMask = clipStencilMask - 1;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001533
1534 unsigned int frontRef = settings->fFrontFuncRef;
1535 unsigned int frontMask = settings->fFrontFuncMask;
1536 unsigned int frontWriteMask = settings->fFrontWriteMask;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001537 GrGLenum frontFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001538
1539 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1540
1541 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
1542 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
1543 } else {
1544 frontFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fFrontFunc)];
1545
1546 ConvertStencilFuncAndMask(settings->fFrontFunc,
1547 stencilClip,
1548 clipStencilMask,
1549 userStencilMask,
1550 &frontRef,
1551 &frontMask);
1552 frontWriteMask &= userStencilMask;
1553 }
1554 GrAssert(settings->fFrontFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001555 (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001556 GrAssert(settings->fFrontPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001557 (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001558 GrAssert(settings->fBackFailOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001559 (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001560 GrAssert(settings->fBackPassOp >= 0 &&
bsalomon@google.com2022c942011-03-30 21:43:04 +00001561 (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001562 if (fTwoSidedStencilSupport) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001563 GrGLenum backFunc;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001564
1565 unsigned int backRef = settings->fBackFuncRef;
1566 unsigned int backMask = settings->fBackFuncMask;
1567 unsigned int backWriteMask = settings->fBackWriteMask;
1568
1569
1570 if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
1571 GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
1572 backFunc = grToGLStencilFunc[settings->fBackFunc];
1573 } else {
1574 backFunc = grToGLStencilFunc[ConvertStencilFunc(stencilClip, settings->fBackFunc)];
1575 ConvertStencilFuncAndMask(settings->fBackFunc,
1576 stencilClip,
1577 clipStencilMask,
1578 userStencilMask,
1579 &backRef,
1580 &backMask);
1581 backWriteMask &= userStencilMask;
1582 }
1583
twiz@google.com0f31ca72011-03-18 17:38:11 +00001584 GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask));
1585 GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask));
1586 GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask));
1587 GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask));
1588 GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001589 grToGLStencilOp[settings->fFrontPassOp],
1590 grToGLStencilOp[settings->fFrontPassOp]));
1591
twiz@google.com0f31ca72011-03-18 17:38:11 +00001592 GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp],
bsalomon@google.comd302f142011-03-03 13:54:13 +00001593 grToGLStencilOp[settings->fBackPassOp],
1594 grToGLStencilOp[settings->fBackPassOp]));
1595 } else {
1596 GR_GL(StencilFunc(frontFunc, frontRef, frontMask));
1597 GR_GL(StencilMask(frontWriteMask));
1598 GR_GL(StencilOp(grToGLStencilOp[settings->fFrontFailOp],
1599 grToGLStencilOp[settings->fFrontPassOp],
1600 grToGLStencilOp[settings->fFrontPassOp]));
1601 }
1602 }
1603 fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
reed@google.comac10a2d2010-12-22 21:39:39 +00001604 fHWStencilClip = stencilClip;
1605 }
1606}
1607
bsalomon@google.com0650e812011-04-08 18:07:53 +00001608bool GrGpuGL::useSmoothLines() {
1609 // there is a conflict between using smooth lines and our use of
1610 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1611 // but not in a premul-alpha way. So we only use them when our alpha
1612 // is 0xff.
1613
1614 // TODO: write a smarter line frag shader.
1615
1616 return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
1617 canDisableBlend();
1618}
1619
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001620void GrGpuGL::flushAAState(GrPrimitiveType type) {
1621 if (GR_GL_SUPPORT_DESKTOP) {
1622 // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
1623 // smooth lines.
1624
1625 // we prefer smooth lines over multisampled lines
1626 // msaa should be disabled if drawing smooth lines.
bsalomon@google.com0650e812011-04-08 18:07:53 +00001627 if (GrIsPrimTypeLines(type)) {
1628 bool smooth = useSmoothLines();
1629 if (!fHWAAState.fSmoothLineEnabled && smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001630 GR_GL(Enable(GR_GL_LINE_SMOOTH));
1631 fHWAAState.fSmoothLineEnabled = true;
bsalomon@google.com0650e812011-04-08 18:07:53 +00001632 } else if (fHWAAState.fSmoothLineEnabled && !smooth) {
bsalomon@google.comf954d8d2011-04-06 17:50:02 +00001633 GR_GL(Disable(GR_GL_LINE_SMOOTH));
1634 fHWAAState.fSmoothLineEnabled = false;
1635 }
1636 if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1637 fHWAAState.fMSAAEnabled) {
1638 GR_GL(Disable(GR_GL_MULTISAMPLE));
1639 fHWAAState.fMSAAEnabled = false;
1640 }
1641 } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
1642 !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
1643 fHWAAState.fMSAAEnabled) {
1644 if (fHWAAState.fMSAAEnabled) {
1645 GR_GL(Disable(GR_GL_MULTISAMPLE));
1646 fHWAAState.fMSAAEnabled = false;
1647 } else {
1648 GR_GL(Enable(GR_GL_MULTISAMPLE));
1649 fHWAAState.fMSAAEnabled = true;
1650 }
1651 }
1652 }
1653}
1654
bsalomon@google.com0650e812011-04-08 18:07:53 +00001655void GrGpuGL::flushBlend(GrPrimitiveType type) {
1656 if (GrIsPrimTypeLines(type) && useSmoothLines()) {
1657 if (fHWBlendDisabled) {
1658 GR_GL(Enable(GR_GL_BLEND));
1659 fHWBlendDisabled = false;
1660 }
1661 if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
1662 kISA_BlendCoeff != fHWDrawState.fDstBlend) {
1663 GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
1664 gXfermodeCoeff2Blend[kISA_BlendCoeff]));
1665 fHWDrawState.fSrcBlend = kSA_BlendCoeff;
1666 fHWDrawState.fDstBlend = kISA_BlendCoeff;
1667 }
1668 } else {
1669 bool blendOff = canDisableBlend();
1670 if (fHWBlendDisabled != blendOff) {
1671 if (blendOff) {
1672 GR_GL(Disable(GR_GL_BLEND));
1673 } else {
1674 GR_GL(Enable(GR_GL_BLEND));
1675 }
1676 fHWBlendDisabled = blendOff;
1677 }
1678 if (!blendOff) {
1679 if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend ||
1680 fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) {
1681 GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend],
1682 gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend]));
1683 fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
1684 fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
1685 }
1686 if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
1687 BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
1688 fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
1689
1690 float c[] = {
1691 GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
1692 GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
1693 GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
1694 GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
1695 };
1696 GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
1697 fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
1698 }
1699 }
1700 }
1701}
1702
bsalomon@google.comffca4002011-02-22 20:34:01 +00001703bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001704
1705 // GrGpu::setupClipAndFlushState should have already checked this
1706 // and bailed if not true.
1707 GrAssert(NULL != fCurrDrawState.fRenderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001708
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001709 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001710 // bind texture and set sampler state
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001711 if (this->isStageEnabled(s)) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001712 GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
reed@google.comac10a2d2010-12-22 21:39:39 +00001713
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001714 // true for now, but maybe not with GrEffect.
1715 GrAssert(NULL != nextTexture);
1716 // if we created a rt/tex and rendered to it without using a
1717 // texture and now we're texuring from the rt it will still be
1718 // the last bound texture, but it needs resolving. So keep this
1719 // out of the "last != next" check.
1720 GrGLRenderTarget* texRT =
1721 static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget());
1722 if (NULL != texRT) {
1723 resolveRenderTarget(texRT);
reed@google.comac10a2d2010-12-22 21:39:39 +00001724 }
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001725
1726 if (fHWDrawState.fTextures[s] != nextTexture) {
1727 setTextureUnit(s);
1728 GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
1729 #if GR_COLLECT_STATS
1730 ++fStats.fTextureChngCnt;
1731 #endif
1732 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
1733 fHWDrawState.fTextures[s] = nextTexture;
1734 }
1735
1736 const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
1737 const GrGLTexture::TexParams& oldTexParams =
1738 nextTexture->getTexParams();
1739 GrGLTexture::TexParams newTexParams;
1740
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +00001741 if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
1742 newTexParams.fFilter = GR_GL_NEAREST;
1743 } else {
1744 newTexParams.fFilter = GR_GL_LINEAR;
1745 }
1746
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001747 newTexParams.fWrapS =
1748 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()];
1749 newTexParams.fWrapT =
1750 GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()];
1751
1752 if (newTexParams.fFilter != oldTexParams.fFilter) {
1753 setTextureUnit(s);
1754 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1755 GR_GL_TEXTURE_MAG_FILTER,
1756 newTexParams.fFilter));
1757 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1758 GR_GL_TEXTURE_MIN_FILTER,
1759 newTexParams.fFilter));
1760 }
1761 if (newTexParams.fWrapS != oldTexParams.fWrapS) {
1762 setTextureUnit(s);
1763 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1764 GR_GL_TEXTURE_WRAP_S,
1765 newTexParams.fWrapS));
1766 }
1767 if (newTexParams.fWrapT != oldTexParams.fWrapT) {
1768 setTextureUnit(s);
1769 GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
1770 GR_GL_TEXTURE_WRAP_T,
1771 newTexParams.fWrapT));
1772 }
1773 nextTexture->setTexParams(newTexParams);
1774
1775 // The texture matrix has to compensate for texture width/height
1776 // and NPOT-embedded-in-POT
1777 fDirtyFlags.fTextureChangedMask |= (1 << s);
reed@google.comac10a2d2010-12-22 21:39:39 +00001778 }
1779 }
1780
bsalomon@google.com8295dc12011-05-02 12:53:34 +00001781 GrIRect* rect = NULL;
1782 GrIRect clipBounds;
1783 if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
1784 fClip.hasConservativeBounds()) {
1785 fClip.getConservativeBounds().roundOut(&clipBounds);
1786 rect = &clipBounds;
1787 }
1788 this->flushRenderTarget(rect);
1789 this->flushAAState(type);
1790 this->flushBlend(type);
bsalomon@google.com0650e812011-04-08 18:07:53 +00001791
reed@google.comac10a2d2010-12-22 21:39:39 +00001792 if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
1793 (fHWDrawState.fFlagBits & kDither_StateBit)) {
1794 if (fCurrDrawState.fFlagBits & kDither_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001795 GR_GL(Enable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001796 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001797 GR_GL(Disable(GR_GL_DITHER));
reed@google.comac10a2d2010-12-22 21:39:39 +00001798 }
1799 }
1800
bsalomon@google.comd302f142011-03-03 13:54:13 +00001801 if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
1802 (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001803 GrGLenum mask;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001804 if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001805 mask = GR_GL_FALSE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001806 } else {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001807 mask = GR_GL_TRUE;
bsalomon@google.comd302f142011-03-03 13:54:13 +00001808 }
1809 GR_GL(ColorMask(mask, mask, mask, mask));
1810 }
1811
bsalomon@google.comd302f142011-03-03 13:54:13 +00001812 if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
1813 switch (fCurrDrawState.fDrawFace) {
1814 case kCCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001815 GR_GL(Enable(GR_GL_CULL_FACE));
1816 GR_GL(CullFace(GR_GL_BACK));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001817 break;
1818 case kCW_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001819 GR_GL(Enable(GR_GL_CULL_FACE));
1820 GR_GL(CullFace(GR_GL_FRONT));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001821 break;
1822 case kBoth_DrawFace:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001823 GR_GL(Disable(GR_GL_CULL_FACE));
bsalomon@google.comd302f142011-03-03 13:54:13 +00001824 break;
1825 default:
1826 GrCrash("Unknown draw face.");
1827 }
1828 fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
1829 }
1830
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001831#if GR_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +00001832 // check for circular rendering
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001833 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +00001834 GrAssert(!this->isStageEnabled(s) ||
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001835 NULL == fCurrDrawState.fRenderTarget ||
1836 NULL == fCurrDrawState.fTextures[s] ||
bsalomon@google.com316f99232011-01-13 21:28:12 +00001837 fCurrDrawState.fTextures[s]->asRenderTarget() !=
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001838 fCurrDrawState.fRenderTarget);
1839 }
1840#endif
bsalomon@google.com316f99232011-01-13 21:28:12 +00001841
reed@google.comac10a2d2010-12-22 21:39:39 +00001842 flushStencil();
1843
bsalomon@google.comd302f142011-03-03 13:54:13 +00001844 // flushStencil may look at the private state bits, so keep it before this.
reed@google.comac10a2d2010-12-22 21:39:39 +00001845 fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001846 return true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001847}
1848
1849void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001850 if (fHWGeometryState.fVertexBuffer != buffer) {
1851 fHWGeometryState.fArrayPtrsDirty = true;
1852 fHWGeometryState.fVertexBuffer = buffer;
1853 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001854}
1855
1856void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001857 if (fHWGeometryState.fVertexBuffer == buffer) {
1858 // deleting bound buffer does implied bind to 0
1859 fHWGeometryState.fVertexBuffer = NULL;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001860 fHWGeometryState.fArrayPtrsDirty = true;
reed@google.comac10a2d2010-12-22 21:39:39 +00001861 }
1862}
1863
1864void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
1865 fGeometrySrc.fIndexBuffer = buffer;
1866}
1867
1868void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001869 if (fHWGeometryState.fIndexBuffer == buffer) {
1870 // deleting bound buffer does implied bind to 0
1871 fHWGeometryState.fIndexBuffer = NULL;
1872 }
1873}
1874
reed@google.comac10a2d2010-12-22 21:39:39 +00001875void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
1876 GrAssert(NULL != renderTarget);
reed@google.comac10a2d2010-12-22 21:39:39 +00001877 if (fCurrDrawState.fRenderTarget == renderTarget) {
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +00001878 fCurrDrawState.fRenderTarget = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +00001879 }
1880 if (fHWDrawState.fRenderTarget == renderTarget) {
1881 fHWDrawState.fRenderTarget = NULL;
1882 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001883}
1884
1885void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001886 for (int s = 0; s < kNumStages; ++s) {
1887 if (fCurrDrawState.fTextures[s] == texture) {
1888 fCurrDrawState.fTextures[s] = NULL;
1889 }
1890 if (fHWDrawState.fTextures[s] == texture) {
1891 // deleting bound texture does implied bind to 0
1892 fHWDrawState.fTextures[s] = NULL;
1893 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001894 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001895}
1896
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001897bool GrGpuGL::canBeTexture(GrPixelConfig config,
twiz@google.com0f31ca72011-03-18 17:38:11 +00001898 GrGLenum* internalFormat,
1899 GrGLenum* format,
1900 GrGLenum* type) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001901 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001902 case kRGBA_8888_GrPixelConfig:
1903 case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X?
bsalomon@google.com2fbc7fa2011-01-05 16:34:41 +00001904 *format = GR_GL_32BPP_COLOR_FORMAT;
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001905 if (GR_GL_SUPPORT_ES) {
1906 // according to GL_EXT_texture_format_BGRA8888 the *internal*
1907 // format for a BGRA is BGRA not RGBA (as on desktop)
1908 *internalFormat = GR_GL_32BPP_COLOR_FORMAT;
1909 } else {
1910 *internalFormat = GR_GL_RGBA;
1911 }
twiz@google.com0f31ca72011-03-18 17:38:11 +00001912 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001913 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001914 case kRGB_565_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001915 *format = GR_GL_RGB;
1916 *internalFormat = GR_GL_RGB;
1917 *type = GR_GL_UNSIGNED_SHORT_5_6_5;
reed@google.comac10a2d2010-12-22 21:39:39 +00001918 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001919 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001920 *format = GR_GL_RGBA;
1921 *internalFormat = GR_GL_RGBA;
1922 *type = GR_GL_UNSIGNED_SHORT_4_4_4_4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001923 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001924 case kIndex_8_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001925 if (this->supports8BitPalette()) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001926 *format = GR_GL_PALETTE8_RGBA8;
1927 *internalFormat = GR_GL_PALETTE8_RGBA8;
twiz@google.com0f31ca72011-03-18 17:38:11 +00001928 *type = GR_GL_UNSIGNED_BYTE; // unused I think
reed@google.comac10a2d2010-12-22 21:39:39 +00001929 } else {
1930 return false;
1931 }
1932 break;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001933 case kAlpha_8_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001934 *format = GR_GL_ALPHA;
1935 *internalFormat = GR_GL_ALPHA;
1936 *type = GR_GL_UNSIGNED_BYTE;
reed@google.comac10a2d2010-12-22 21:39:39 +00001937 break;
1938 default:
1939 return false;
1940 }
1941 return true;
1942}
1943
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001944void GrGpuGL::setTextureUnit(int unit) {
1945 GrAssert(unit >= 0 && unit < kNumStages);
1946 if (fActiveTextureUnitIdx != unit) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001947 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001948 fActiveTextureUnitIdx = unit;
1949 }
1950}
bsalomon@google.com316f99232011-01-13 21:28:12 +00001951
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001952void GrGpuGL::setSpareTextureUnit() {
twiz@google.com0f31ca72011-03-18 17:38:11 +00001953 if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) {
1954 GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +00001955 fActiveTextureUnitIdx = SPARE_TEX_UNIT;
1956 }
1957}
1958
reed@google.comac10a2d2010-12-22 21:39:39 +00001959/* On ES the internalFormat and format must match for TexImage and we use
1960 GL_RGB, GL_RGBA for color formats. We also generally like having the driver
1961 decide the internalFormat. However, on ES internalFormat for
1962 RenderBufferStorage* has to be a specific format (not a base format like
1963 GL_RGBA).
1964 */
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001965bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) {
reed@google.comac10a2d2010-12-22 21:39:39 +00001966 switch (config) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001967 case kRGBA_8888_GrPixelConfig:
1968 case kRGBX_8888_GrPixelConfig:
reed@google.comac10a2d2010-12-22 21:39:39 +00001969 if (fRGBA8Renderbuffer) {
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001970 *format = GR_GL_RGBA8;
reed@google.comac10a2d2010-12-22 21:39:39 +00001971 return true;
1972 } else {
1973 return false;
1974 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001975 case kRGB_565_GrPixelConfig:
twiz@google.comb65e0cb2011-03-18 20:41:44 +00001976 GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it
1977 // with FBO extension desktop GL has
1978 // no such internal format
bsalomon@google.comc312bf92011-03-21 21:10:33 +00001979 *format = GR_GL_RGB565;
reed@google.comac10a2d2010-12-22 21:39:39 +00001980 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +00001981 case kRGBA_4444_GrPixelConfig:
twiz@google.com0f31ca72011-03-18 17:38:11 +00001982 *format = GR_GL_RGBA4;
reed@google.comac10a2d2010-12-22 21:39:39 +00001983 return true;
1984 default:
1985 return false;
1986 }
1987}
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001988
bsalomon@google.comc6cf7232011-02-17 16:43:10 +00001989void GrGpuGL::resetDirtyFlags() {
1990 Gr_bzero(&fDirtyFlags, sizeof(fDirtyFlags));
1991}
1992
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001993void GrGpuGL::setBuffers(bool indexed,
1994 int* extraVertexOffset,
1995 int* extraIndexOffset) {
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001996
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001997 GrAssert(NULL != extraVertexOffset);
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00001998
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001999 GrGLVertexBuffer* vbuf;
2000 switch (fGeometrySrc.fVertexSrc) {
2001 case kBuffer_GeometrySrcType:
2002 *extraVertexOffset = 0;
2003 vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
2004 break;
2005 case kArray_GeometrySrcType:
2006 case kReserved_GeometrySrcType:
2007 finalizeReservedVertices();
2008 *extraVertexOffset = fCurrPoolStartVertex;
2009 vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
2010 break;
2011 default:
2012 vbuf = NULL; // suppress warning
2013 GrCrash("Unknown geometry src type!");
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002014 }
2015
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002016 GrAssert(NULL != vbuf);
2017 GrAssert(!vbuf->isLocked());
2018 if (fHWGeometryState.fVertexBuffer != vbuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002019 GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002020 fHWGeometryState.fArrayPtrsDirty = true;
2021 fHWGeometryState.fVertexBuffer = vbuf;
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002022 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002023
2024 if (indexed) {
2025 GrAssert(NULL != extraIndexOffset);
2026
2027 GrGLIndexBuffer* ibuf;
2028 switch (fGeometrySrc.fIndexSrc) {
2029 case kBuffer_GeometrySrcType:
2030 *extraIndexOffset = 0;
2031 ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
2032 break;
2033 case kArray_GeometrySrcType:
2034 case kReserved_GeometrySrcType:
2035 finalizeReservedIndices();
2036 *extraIndexOffset = fCurrPoolStartIndex;
2037 ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
2038 break;
2039 default:
2040 ibuf = NULL; // suppress warning
2041 GrCrash("Unknown geometry src type!");
2042 }
2043
2044 GrAssert(NULL != ibuf);
2045 GrAssert(!ibuf->isLocked());
2046 if (fHWGeometryState.fIndexBuffer != ibuf) {
twiz@google.com0f31ca72011-03-18 17:38:11 +00002047 GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
bsalomon@google.com1c13c962011-02-14 16:51:21 +00002048 fHWGeometryState.fIndexBuffer = ibuf;
2049 }
2050 }
bsalomon@google.com7acdb8e2011-02-11 14:07:02 +00002051}
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00002052
2053int GrGpuGL::getMaxEdges() const {
2054 // FIXME: This is a pessimistic estimate based on how many other things
2055 // want to add uniforms. This should be centralized somewhere.
2056 return GR_CT_MIN(fMaxFragmentUniformVectors - 8, kMaxEdges);
2057}