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