blob: ec125b7712e5466cc2a9f8b616dcc425fbdf3fbd [file] [log] [blame]
bsalomon@google.comf7fa8062012-02-14 14:09:57 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9#include "GrGLCaps.h"
10#include "GrGLContextInfo.h"
bsalomon@google.comc9668ec2012-04-11 18:16:41 +000011#include "SkTSearch.h"
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000012
13GrGLCaps::GrGLCaps() {
14 this->reset();
15}
16
17void GrGLCaps::reset() {
18 fVerifiedColorConfigs.reset();
19 fStencilFormats.reset();
20 fStencilVerifiedColorConfigs.reset();
21 fMSFBOType = kNone_MSFBOType;
bsalomon@google.comf6b070d2012-04-27 14:25:44 +000022 fMaxSampleCount = 0;
bsalomon@google.comc9668ec2012-04-11 18:16:41 +000023 fCoverageAAType = kNone_CoverageAAType;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000024 fMaxFragmentUniformVectors = 0;
bsalomon@google.com60da4172012-06-01 19:25:00 +000025 fMaxVertexAttributes = 0;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000026 fRGBA8RenderbufferSupport = false;
27 fBGRAFormatSupport = false;
28 fBGRAIsInternalFormat = false;
29 fTextureSwizzleSupport = false;
30 fUnpackRowLengthSupport = false;
31 fUnpackFlipYSupport = false;
32 fPackRowLengthSupport = false;
33 fPackFlipYSupport = false;
34 fTextureUsageSupport = false;
35 fTexStorageSupport = false;
robertphillips@google.com443e5a52012-04-30 20:01:21 +000036 fTextureRedSupport = false;
bsalomon@google.come76b7cc2012-06-18 12:47:06 +000037 fImagingSupport = false;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000038}
39
40GrGLCaps::GrGLCaps(const GrGLCaps& caps) {
41 *this = caps;
42}
43
44GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
45 fVerifiedColorConfigs = caps.fVerifiedColorConfigs;
46 fStencilFormats = caps.fStencilFormats;
47 fStencilVerifiedColorConfigs = caps.fStencilVerifiedColorConfigs;
48 fMaxFragmentUniformVectors = caps.fMaxFragmentUniformVectors;
bsalomon@google.com60da4172012-06-01 19:25:00 +000049 fMaxVertexAttributes = caps.fMaxVertexAttributes;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000050 fMSFBOType = caps.fMSFBOType;
bsalomon@google.comf6b070d2012-04-27 14:25:44 +000051 fMaxSampleCount = caps.fMaxSampleCount;
bsalomon@google.comc9668ec2012-04-11 18:16:41 +000052 fCoverageAAType = caps.fCoverageAAType;
53 fMSAACoverageModes = caps.fMSAACoverageModes;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000054 fRGBA8RenderbufferSupport = caps.fRGBA8RenderbufferSupport;
55 fBGRAFormatSupport = caps.fBGRAFormatSupport;
56 fBGRAIsInternalFormat = caps.fBGRAIsInternalFormat;
57 fTextureSwizzleSupport = caps.fTextureSwizzleSupport;
58 fUnpackRowLengthSupport = caps.fUnpackRowLengthSupport;
59 fUnpackFlipYSupport = caps.fUnpackFlipYSupport;
60 fPackRowLengthSupport = caps.fPackRowLengthSupport;
61 fPackFlipYSupport = caps.fPackFlipYSupport;
62 fTextureUsageSupport = caps.fTextureUsageSupport;
63 fTexStorageSupport = caps.fTexStorageSupport;
robertphillips@google.com443e5a52012-04-30 20:01:21 +000064 fTextureRedSupport = caps.fTextureRedSupport;
bsalomon@google.come76b7cc2012-06-18 12:47:06 +000065 fImagingSupport = caps.fImagingSupport;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000066
67 return *this;
68}
69
70void GrGLCaps::init(const GrGLContextInfo& ctxInfo) {
71
72 this->reset();
73 if (!ctxInfo.isInitialized()) {
74 return;
75 }
76
77 const GrGLInterface* gli = ctxInfo.interface();
78 GrGLBinding binding = ctxInfo.binding();
79 GrGLVersion version = ctxInfo.version();
80
81 if (kES2_GrGLBinding == binding) {
82 GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
83 &fMaxFragmentUniformVectors);
84 } else {
85 GrAssert(kDesktop_GrGLBinding == binding);
86 GrGLint max;
87 GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
88 fMaxFragmentUniformVectors = max / 4;
89 }
bsalomon@google.com60da4172012-06-01 19:25:00 +000090 GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttributes);
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000091
92 if (kDesktop_GrGLBinding == binding) {
93 fRGBA8RenderbufferSupport = true;
94 } else {
95 fRGBA8RenderbufferSupport = ctxInfo.hasExtension("GL_OES_rgb8_rgba8") ||
96 ctxInfo.hasExtension("GL_ARM_rgba8");
97 }
98
99 if (kDesktop_GrGLBinding == binding) {
100 fBGRAFormatSupport = version >= GR_GL_VER(1,2) ||
101 ctxInfo.hasExtension("GL_EXT_bgra");
102 } else {
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000103 if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) {
104 fBGRAFormatSupport = true;
105 } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) {
106 fBGRAFormatSupport = true;
107 fBGRAIsInternalFormat = true;
108 }
109 GrAssert(fBGRAFormatSupport ||
110 kSkia8888_PM_GrPixelConfig != kBGRA_8888_PM_GrPixelConfig);
111 }
112
113 if (kDesktop_GrGLBinding == binding) {
114 fTextureSwizzleSupport = version >= GR_GL_VER(3,3) ||
115 ctxInfo.hasExtension("GL_ARB_texture_swizzle");
116 } else {
117 fTextureSwizzleSupport = false;
118 }
119
120 if (kDesktop_GrGLBinding == binding) {
121 fUnpackRowLengthSupport = true;
122 fUnpackFlipYSupport = false;
123 fPackRowLengthSupport = true;
124 fPackFlipYSupport = false;
125 } else {
126 fUnpackRowLengthSupport =ctxInfo.hasExtension("GL_EXT_unpack_subimage");
127 fUnpackFlipYSupport = ctxInfo.hasExtension("GL_CHROMIUM_flipy");
128 // no extension for pack row length
129 fPackRowLengthSupport = false;
130 fPackFlipYSupport =
131 ctxInfo.hasExtension("GL_ANGLE_pack_reverse_row_order");
132 }
133
134 fTextureUsageSupport = (kES2_GrGLBinding == binding) &&
135 ctxInfo.hasExtension("GL_ANGLE_texture_usage");
136
137 // Tex storage is in desktop 4.2 and can be an extension to desktop or ES.
138 fTexStorageSupport = (kDesktop_GrGLBinding == binding &&
139 version >= GR_GL_VER(4,2)) ||
140 ctxInfo.hasExtension("GL_ARB_texture_storage") ||
141 ctxInfo.hasExtension("GL_EXT_texture_storage");
142
robertphillips@google.com443e5a52012-04-30 20:01:21 +0000143 // ARB_texture_rg is part of OpenGL 3.0
144 if (kDesktop_GrGLBinding == binding) {
145 fTextureRedSupport = version >= GR_GL_VER(3,0) ||
146 ctxInfo.hasExtension("GL_ARB_texture_rg");
147 } else {
148 fTextureRedSupport = ctxInfo.hasExtension("GL_EXT_texture_rg");
149 }
150
bsalomon@google.come76b7cc2012-06-18 12:47:06 +0000151 fImagingSupport = kDesktop_GrGLBinding == binding &&
152 ctxInfo.hasExtension("GL_ARB_imaging");
153
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000154 this->initFSAASupport(ctxInfo);
155 this->initStencilFormats(ctxInfo);
156}
157
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000158namespace {
159int coverage_mode_compare(const GrGLCaps::MSAACoverageMode* left,
160 const GrGLCaps::MSAACoverageMode* right) {
161 if (left->fCoverageSampleCnt < right->fCoverageSampleCnt) {
162 return -1;
163 } else if (right->fCoverageSampleCnt < left->fCoverageSampleCnt) {
164 return 1;
165 } else if (left->fColorSampleCnt < right->fColorSampleCnt) {
166 return -1;
167 } else if (right->fColorSampleCnt < left->fColorSampleCnt) {
168 return 1;
169 }
170 return 0;
171}
172}
173
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000174void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo) {
175
176 fMSFBOType = kNone_MSFBOType;
177 if (kDesktop_GrGLBinding != ctxInfo.binding()) {
178 if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
179 // chrome's extension is equivalent to the EXT msaa
180 // and fbo_blit extensions.
181 fMSFBOType = kDesktopEXT_MSFBOType;
182 } else if (ctxInfo.hasExtension("GL_APPLE_framebuffer_multisample")) {
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000183 fMSFBOType = kAppleES_MSFBOType;
184 }
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000185 } else {
186 if ((ctxInfo.version() >= GR_GL_VER(3,0)) ||
187 ctxInfo.hasExtension("GL_ARB_framebuffer_object")) {
188 fMSFBOType = GrGLCaps::kDesktopARB_MSFBOType;
189 } else if (ctxInfo.hasExtension("GL_EXT_framebuffer_multisample") &&
190 ctxInfo.hasExtension("GL_EXT_framebuffer_blit")) {
191 fMSFBOType = GrGLCaps::kDesktopEXT_MSFBOType;
192 }
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000193 // TODO: We could populate fMSAACoverageModes using GetInternalformativ
194 // on GL 4.2+. It's format-specific, though. See also
195 // http://code.google.com/p/skia/issues/detail?id=470 about using actual
196 // rather than requested sample counts in cache key.
197 if (ctxInfo.hasExtension("GL_NV_framebuffer_multisample_coverage")) {
198 fCoverageAAType = kNVDesktop_CoverageAAType;
199 GrGLint count;
200 GR_GL_GetIntegerv(ctxInfo.interface(),
201 GR_GL_MAX_MULTISAMPLE_COVERAGE_MODES,
202 &count);
203 fMSAACoverageModes.setCount(count);
204 GR_GL_GetIntegerv(ctxInfo.interface(),
205 GR_GL_MULTISAMPLE_COVERAGE_MODES,
206 (int*)&fMSAACoverageModes[0]);
207 // The NV driver seems to return the modes already sorted but the
208 // spec doesn't require this. So we sort.
reed@google.comc7a67cb2012-05-07 14:52:12 +0000209 qsort(&fMSAACoverageModes[0],
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000210 count,
211 sizeof(MSAACoverageMode),
reed@google.comc7a67cb2012-05-07 14:52:12 +0000212 SkCastForQSort(coverage_mode_compare));
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000213 }
214 }
bsalomon@google.comf6b070d2012-04-27 14:25:44 +0000215 if (kNone_MSFBOType != fMSFBOType) {
216 GR_GL_GetIntegerv(ctxInfo.interface(),
217 GR_GL_MAX_SAMPLES,
218 &fMaxSampleCount);
219 }
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000220}
221
222const GrGLCaps::MSAACoverageMode& GrGLCaps::getMSAACoverageMode(
223 int desiredSampleCount) const {
224 static const MSAACoverageMode kNoneMode = {0, 0};
225 if (0 == fMSAACoverageModes.count()) {
226 return kNoneMode;
227 } else {
228 GrAssert(kNone_CoverageAAType != fCoverageAAType);
229 int max = (fMSAACoverageModes.end() - 1)->fCoverageSampleCnt;
230 desiredSampleCount = GrMin(desiredSampleCount, max);
231 MSAACoverageMode desiredMode = {desiredSampleCount, 0};
232 int idx = SkTSearch<MSAACoverageMode>(&fMSAACoverageModes[0],
233 fMSAACoverageModes.count(),
234 desiredMode,
235 sizeof(MSAACoverageMode),
236 &coverage_mode_compare);
237 if (idx < 0) {
238 idx = ~idx;
239 }
240 GrAssert(idx >= 0 && idx < fMSAACoverageModes.count());
241 return fMSAACoverageModes[idx];
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000242 }
243}
244
245namespace {
246const GrGLuint kUnknownBitCount = GrGLStencilBuffer::kUnknownBitCount;
247}
248
249void GrGLCaps::initStencilFormats(const GrGLContextInfo& ctxInfo) {
250
251 // Build up list of legal stencil formats (though perhaps not supported on
252 // the particular gpu/driver) from most preferred to least.
253
254 // these consts are in order of most preferred to least preferred
255 // we don't bother with GL_STENCIL_INDEX1 or GL_DEPTH32F_STENCIL8
256
257 static const StencilFormat
258 // internal Format stencil bits total bits packed?
259 gS8 = {GR_GL_STENCIL_INDEX8, 8, 8, false},
260 gS16 = {GR_GL_STENCIL_INDEX16, 16, 16, false},
261 gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, 32, true },
262 gS4 = {GR_GL_STENCIL_INDEX4, 4, 4, false},
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000263 // gS = {GR_GL_STENCIL_INDEX, kUnknownBitCount, kUnknownBitCount, false},
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000264 gDS = {GR_GL_DEPTH_STENCIL, kUnknownBitCount, kUnknownBitCount, true };
265
266 if (kDesktop_GrGLBinding == ctxInfo.binding()) {
267 bool supportsPackedDS =
268 ctxInfo.version() >= GR_GL_VER(3,0) ||
269 ctxInfo.hasExtension("GL_EXT_packed_depth_stencil") ||
270 ctxInfo.hasExtension("GL_ARB_framebuffer_object");
271
272 // S1 thru S16 formats are in GL 3.0+, EXT_FBO, and ARB_FBO since we
273 // require FBO support we can expect these are legal formats and don't
274 // check. These also all support the unsized GL_STENCIL_INDEX.
275 fStencilFormats.push_back() = gS8;
276 fStencilFormats.push_back() = gS16;
277 if (supportsPackedDS) {
278 fStencilFormats.push_back() = gD24S8;
279 }
280 fStencilFormats.push_back() = gS4;
281 if (supportsPackedDS) {
282 fStencilFormats.push_back() = gDS;
283 }
284 } else {
285 // ES2 has STENCIL_INDEX8 without extensions but requires extensions
286 // for other formats.
287 // ES doesn't support using the unsized format.
288
289 fStencilFormats.push_back() = gS8;
290 //fStencilFormats.push_back() = gS16;
291 if (ctxInfo.hasExtension("GL_OES_packed_depth_stencil")) {
292 fStencilFormats.push_back() = gD24S8;
293 }
294 if (ctxInfo.hasExtension("GL_OES_stencil4")) {
295 fStencilFormats.push_back() = gS4;
296 }
297 }
298 GrAssert(0 == fStencilVerifiedColorConfigs.count());
299 fStencilVerifiedColorConfigs.push_back_n(fStencilFormats.count());
300}
301
302void GrGLCaps::markColorConfigAndStencilFormatAsVerified(
303 GrPixelConfig config,
304 const GrGLStencilBuffer::Format& format) {
305#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT
306 return;
307#endif
308 GrAssert((unsigned)config < kGrPixelConfigCount);
309 GrAssert(fStencilFormats.count() == fStencilVerifiedColorConfigs.count());
310 int count = fStencilFormats.count();
311 // we expect a really small number of possible formats so linear search
312 // should be OK
313 GrAssert(count < 16);
314 for (int i = 0; i < count; ++i) {
315 if (format.fInternalFormat ==
316 fStencilFormats[i].fInternalFormat) {
317 fStencilVerifiedColorConfigs[i].markVerified(config);
318 return;
319 }
320 }
321 GrCrash("Why are we seeing a stencil format that "
322 "GrGLCaps doesn't know about.");
323}
324
325bool GrGLCaps::isColorConfigAndStencilFormatVerified(
326 GrPixelConfig config,
327 const GrGLStencilBuffer::Format& format) const {
328#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT
329 return false;
330#endif
331 GrAssert((unsigned)config < kGrPixelConfigCount);
332 int count = fStencilFormats.count();
333 // we expect a really small number of possible formats so linear search
334 // should be OK
335 GrAssert(count < 16);
336 for (int i = 0; i < count; ++i) {
337 if (format.fInternalFormat ==
338 fStencilFormats[i].fInternalFormat) {
339 return fStencilVerifiedColorConfigs[i].isVerified(config);
340 }
341 }
342 GrCrash("Why are we seeing a stencil format that "
343 "GLCaps doesn't know about.");
344 return false;
345}
346
347void GrGLCaps::print() const {
348 for (int i = 0; i < fStencilFormats.count(); ++i) {
349 GrPrintf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n",
350 i,
351 fStencilFormats[i].fStencilBits,
352 fStencilFormats[i].fTotalBits);
353 }
354
355 GR_STATIC_ASSERT(0 == kNone_MSFBOType);
356 GR_STATIC_ASSERT(1 == kDesktopARB_MSFBOType);
357 GR_STATIC_ASSERT(2 == kDesktopEXT_MSFBOType);
358 GR_STATIC_ASSERT(3 == kAppleES_MSFBOType);
359 static const char* gMSFBOExtStr[] = {
360 "None",
361 "ARB",
362 "EXT",
363 "Apple",
364 };
365 GrPrintf("MSAA Type: %s\n", gMSFBOExtStr[fMSFBOType]);
366 GrPrintf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
367 GrPrintf("Support RGBA8 Render Buffer: %s\n",
368 (fRGBA8RenderbufferSupport ? "YES": "NO"));
369 GrPrintf("BGRA is an internal format: %s\n",
370 (fBGRAIsInternalFormat ? "YES": "NO"));
371 GrPrintf("Support texture swizzle: %s\n",
372 (fTextureSwizzleSupport ? "YES": "NO"));
373 GrPrintf("Unpack Row length support: %s\n",
374 (fUnpackRowLengthSupport ? "YES": "NO"));
375 GrPrintf("Unpack Flip Y support: %s\n",
376 (fUnpackFlipYSupport ? "YES": "NO"));
377 GrPrintf("Pack Row length support: %s\n",
378 (fPackRowLengthSupport ? "YES": "NO"));
379 GrPrintf("Pack Flip Y support: %s\n",
380 (fPackFlipYSupport ? "YES": "NO"));
381}
382