blob: 52c480ad3f0ea92860286b2ce24f7241f9bcc46c [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;
robertphillips@google.com1d89c932012-06-27 19:31:41 +000038 fTwoFormatLimit = false;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000039}
40
41GrGLCaps::GrGLCaps(const GrGLCaps& caps) {
42 *this = caps;
43}
44
45GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
46 fVerifiedColorConfigs = caps.fVerifiedColorConfigs;
47 fStencilFormats = caps.fStencilFormats;
48 fStencilVerifiedColorConfigs = caps.fStencilVerifiedColorConfigs;
49 fMaxFragmentUniformVectors = caps.fMaxFragmentUniformVectors;
bsalomon@google.com60da4172012-06-01 19:25:00 +000050 fMaxVertexAttributes = caps.fMaxVertexAttributes;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000051 fMSFBOType = caps.fMSFBOType;
bsalomon@google.comf6b070d2012-04-27 14:25:44 +000052 fMaxSampleCount = caps.fMaxSampleCount;
bsalomon@google.comc9668ec2012-04-11 18:16:41 +000053 fCoverageAAType = caps.fCoverageAAType;
54 fMSAACoverageModes = caps.fMSAACoverageModes;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000055 fRGBA8RenderbufferSupport = caps.fRGBA8RenderbufferSupport;
56 fBGRAFormatSupport = caps.fBGRAFormatSupport;
57 fBGRAIsInternalFormat = caps.fBGRAIsInternalFormat;
58 fTextureSwizzleSupport = caps.fTextureSwizzleSupport;
59 fUnpackRowLengthSupport = caps.fUnpackRowLengthSupport;
60 fUnpackFlipYSupport = caps.fUnpackFlipYSupport;
61 fPackRowLengthSupport = caps.fPackRowLengthSupport;
62 fPackFlipYSupport = caps.fPackFlipYSupport;
63 fTextureUsageSupport = caps.fTextureUsageSupport;
64 fTexStorageSupport = caps.fTexStorageSupport;
robertphillips@google.com443e5a52012-04-30 20:01:21 +000065 fTextureRedSupport = caps.fTextureRedSupport;
bsalomon@google.come76b7cc2012-06-18 12:47:06 +000066 fImagingSupport = caps.fImagingSupport;
robertphillips@google.com1d89c932012-06-27 19:31:41 +000067 fTwoFormatLimit = caps.fTwoFormatLimit;
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000068
69 return *this;
70}
71
72void GrGLCaps::init(const GrGLContextInfo& ctxInfo) {
73
74 this->reset();
75 if (!ctxInfo.isInitialized()) {
76 return;
77 }
78
79 const GrGLInterface* gli = ctxInfo.interface();
80 GrGLBinding binding = ctxInfo.binding();
81 GrGLVersion version = ctxInfo.version();
82
83 if (kES2_GrGLBinding == binding) {
84 GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
85 &fMaxFragmentUniformVectors);
86 } else {
87 GrAssert(kDesktop_GrGLBinding == binding);
88 GrGLint max;
89 GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
90 fMaxFragmentUniformVectors = max / 4;
91 }
bsalomon@google.com60da4172012-06-01 19:25:00 +000092 GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttributes);
bsalomon@google.comf7fa8062012-02-14 14:09:57 +000093
94 if (kDesktop_GrGLBinding == binding) {
95 fRGBA8RenderbufferSupport = true;
96 } else {
97 fRGBA8RenderbufferSupport = ctxInfo.hasExtension("GL_OES_rgb8_rgba8") ||
98 ctxInfo.hasExtension("GL_ARM_rgba8");
99 }
100
101 if (kDesktop_GrGLBinding == binding) {
102 fBGRAFormatSupport = version >= GR_GL_VER(1,2) ||
103 ctxInfo.hasExtension("GL_EXT_bgra");
104 } else {
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000105 if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) {
106 fBGRAFormatSupport = true;
107 } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) {
108 fBGRAFormatSupport = true;
109 fBGRAIsInternalFormat = true;
110 }
111 GrAssert(fBGRAFormatSupport ||
bsalomon@google.com0342a852012-08-20 19:22:38 +0000112 kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig);
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000113 }
114
115 if (kDesktop_GrGLBinding == binding) {
116 fTextureSwizzleSupport = version >= GR_GL_VER(3,3) ||
117 ctxInfo.hasExtension("GL_ARB_texture_swizzle");
118 } else {
119 fTextureSwizzleSupport = false;
120 }
121
122 if (kDesktop_GrGLBinding == binding) {
123 fUnpackRowLengthSupport = true;
124 fUnpackFlipYSupport = false;
125 fPackRowLengthSupport = true;
126 fPackFlipYSupport = false;
127 } else {
128 fUnpackRowLengthSupport =ctxInfo.hasExtension("GL_EXT_unpack_subimage");
129 fUnpackFlipYSupport = ctxInfo.hasExtension("GL_CHROMIUM_flipy");
130 // no extension for pack row length
131 fPackRowLengthSupport = false;
132 fPackFlipYSupport =
133 ctxInfo.hasExtension("GL_ANGLE_pack_reverse_row_order");
134 }
135
136 fTextureUsageSupport = (kES2_GrGLBinding == binding) &&
137 ctxInfo.hasExtension("GL_ANGLE_texture_usage");
138
139 // Tex storage is in desktop 4.2 and can be an extension to desktop or ES.
140 fTexStorageSupport = (kDesktop_GrGLBinding == binding &&
141 version >= GR_GL_VER(4,2)) ||
142 ctxInfo.hasExtension("GL_ARB_texture_storage") ||
143 ctxInfo.hasExtension("GL_EXT_texture_storage");
144
robertphillips@google.com443e5a52012-04-30 20:01:21 +0000145 // ARB_texture_rg is part of OpenGL 3.0
146 if (kDesktop_GrGLBinding == binding) {
147 fTextureRedSupport = version >= GR_GL_VER(3,0) ||
148 ctxInfo.hasExtension("GL_ARB_texture_rg");
149 } else {
150 fTextureRedSupport = ctxInfo.hasExtension("GL_EXT_texture_rg");
151 }
152
bsalomon@google.come76b7cc2012-06-18 12:47:06 +0000153 fImagingSupport = kDesktop_GrGLBinding == binding &&
154 ctxInfo.hasExtension("GL_ARB_imaging");
155
robertphillips@google.com1d89c932012-06-27 19:31:41 +0000156 // ES 2 only guarantees RGBA/uchar + one other format/type combo for
157 // ReadPixels. The other format has to checked at run-time since it
158 // can change based on which render target is bound
159 fTwoFormatLimit = kES2_GrGLBinding == binding;
160
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000161 this->initFSAASupport(ctxInfo);
162 this->initStencilFormats(ctxInfo);
163}
164
robertphillips@google.com1d89c932012-06-27 19:31:41 +0000165bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf,
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000166 GrGLenum format,
167 GrGLenum type) const {
robertphillips@google.com1d89c932012-06-27 19:31:41 +0000168 if (GR_GL_RGBA == format && GR_GL_UNSIGNED_BYTE == type) {
169 // ES 2 guarantees this format is supported
robertphillips@google.comeca2dfb2012-06-27 20:13:49 +0000170 return true;
robertphillips@google.com1d89c932012-06-27 19:31:41 +0000171 }
172
173 if (!fTwoFormatLimit) {
174 // not limited by ES 2's constraints
175 return true;
176 }
177
bsalomon@google.com548a4332012-07-11 19:45:22 +0000178 GrGLint otherFormat = GR_GL_RGBA;
179 GrGLint otherType = GR_GL_UNSIGNED_BYTE;
robertphillips@google.com1d89c932012-06-27 19:31:41 +0000180
181 // The other supported format/type combo supported for ReadPixels
182 // can change based on which render target is bound
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000183 GR_GL_GetIntegerv(intf,
robertphillips@google.com1d89c932012-06-27 19:31:41 +0000184 GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT,
185 &otherFormat);
186
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000187 GR_GL_GetIntegerv(intf,
robertphillips@google.com1d89c932012-06-27 19:31:41 +0000188 GR_GL_IMPLEMENTATION_COLOR_READ_TYPE,
189 &otherType);
190
bsalomon@google.com548a4332012-07-11 19:45:22 +0000191 return (GrGLenum)otherFormat == format && (GrGLenum)otherType == type;
robertphillips@google.com1d89c932012-06-27 19:31:41 +0000192}
193
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000194namespace {
195int coverage_mode_compare(const GrGLCaps::MSAACoverageMode* left,
196 const GrGLCaps::MSAACoverageMode* right) {
197 if (left->fCoverageSampleCnt < right->fCoverageSampleCnt) {
198 return -1;
199 } else if (right->fCoverageSampleCnt < left->fCoverageSampleCnt) {
200 return 1;
201 } else if (left->fColorSampleCnt < right->fColorSampleCnt) {
202 return -1;
203 } else if (right->fColorSampleCnt < left->fColorSampleCnt) {
204 return 1;
205 }
206 return 0;
207}
208}
209
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000210void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo) {
211
212 fMSFBOType = kNone_MSFBOType;
213 if (kDesktop_GrGLBinding != ctxInfo.binding()) {
214 if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
215 // chrome's extension is equivalent to the EXT msaa
216 // and fbo_blit extensions.
217 fMSFBOType = kDesktopEXT_MSFBOType;
218 } else if (ctxInfo.hasExtension("GL_APPLE_framebuffer_multisample")) {
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000219 fMSFBOType = kAppleES_MSFBOType;
220 }
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000221 } else {
222 if ((ctxInfo.version() >= GR_GL_VER(3,0)) ||
223 ctxInfo.hasExtension("GL_ARB_framebuffer_object")) {
224 fMSFBOType = GrGLCaps::kDesktopARB_MSFBOType;
225 } else if (ctxInfo.hasExtension("GL_EXT_framebuffer_multisample") &&
226 ctxInfo.hasExtension("GL_EXT_framebuffer_blit")) {
227 fMSFBOType = GrGLCaps::kDesktopEXT_MSFBOType;
228 }
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000229 // TODO: We could populate fMSAACoverageModes using GetInternalformativ
230 // on GL 4.2+. It's format-specific, though. See also
231 // http://code.google.com/p/skia/issues/detail?id=470 about using actual
232 // rather than requested sample counts in cache key.
233 if (ctxInfo.hasExtension("GL_NV_framebuffer_multisample_coverage")) {
234 fCoverageAAType = kNVDesktop_CoverageAAType;
235 GrGLint count;
236 GR_GL_GetIntegerv(ctxInfo.interface(),
237 GR_GL_MAX_MULTISAMPLE_COVERAGE_MODES,
238 &count);
239 fMSAACoverageModes.setCount(count);
240 GR_GL_GetIntegerv(ctxInfo.interface(),
241 GR_GL_MULTISAMPLE_COVERAGE_MODES,
242 (int*)&fMSAACoverageModes[0]);
243 // The NV driver seems to return the modes already sorted but the
244 // spec doesn't require this. So we sort.
reed@google.comc7a67cb2012-05-07 14:52:12 +0000245 qsort(&fMSAACoverageModes[0],
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000246 count,
247 sizeof(MSAACoverageMode),
reed@google.comc7a67cb2012-05-07 14:52:12 +0000248 SkCastForQSort(coverage_mode_compare));
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000249 }
250 }
bsalomon@google.comf6b070d2012-04-27 14:25:44 +0000251 if (kNone_MSFBOType != fMSFBOType) {
252 GR_GL_GetIntegerv(ctxInfo.interface(),
253 GR_GL_MAX_SAMPLES,
254 &fMaxSampleCount);
255 }
bsalomon@google.comc9668ec2012-04-11 18:16:41 +0000256}
257
258const GrGLCaps::MSAACoverageMode& GrGLCaps::getMSAACoverageMode(
259 int desiredSampleCount) const {
260 static const MSAACoverageMode kNoneMode = {0, 0};
261 if (0 == fMSAACoverageModes.count()) {
262 return kNoneMode;
263 } else {
264 GrAssert(kNone_CoverageAAType != fCoverageAAType);
265 int max = (fMSAACoverageModes.end() - 1)->fCoverageSampleCnt;
266 desiredSampleCount = GrMin(desiredSampleCount, max);
267 MSAACoverageMode desiredMode = {desiredSampleCount, 0};
268 int idx = SkTSearch<MSAACoverageMode>(&fMSAACoverageModes[0],
269 fMSAACoverageModes.count(),
270 desiredMode,
271 sizeof(MSAACoverageMode),
272 &coverage_mode_compare);
273 if (idx < 0) {
274 idx = ~idx;
275 }
276 GrAssert(idx >= 0 && idx < fMSAACoverageModes.count());
277 return fMSAACoverageModes[idx];
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000278 }
279}
280
281namespace {
282const GrGLuint kUnknownBitCount = GrGLStencilBuffer::kUnknownBitCount;
283}
284
285void GrGLCaps::initStencilFormats(const GrGLContextInfo& ctxInfo) {
286
287 // Build up list of legal stencil formats (though perhaps not supported on
288 // the particular gpu/driver) from most preferred to least.
289
290 // these consts are in order of most preferred to least preferred
291 // we don't bother with GL_STENCIL_INDEX1 or GL_DEPTH32F_STENCIL8
292
293 static const StencilFormat
294 // internal Format stencil bits total bits packed?
295 gS8 = {GR_GL_STENCIL_INDEX8, 8, 8, false},
296 gS16 = {GR_GL_STENCIL_INDEX16, 16, 16, false},
297 gD24S8 = {GR_GL_DEPTH24_STENCIL8, 8, 32, true },
298 gS4 = {GR_GL_STENCIL_INDEX4, 4, 4, false},
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000299 // gS = {GR_GL_STENCIL_INDEX, kUnknownBitCount, kUnknownBitCount, false},
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000300 gDS = {GR_GL_DEPTH_STENCIL, kUnknownBitCount, kUnknownBitCount, true };
301
302 if (kDesktop_GrGLBinding == ctxInfo.binding()) {
303 bool supportsPackedDS =
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000304 ctxInfo.version() >= GR_GL_VER(3,0) ||
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000305 ctxInfo.hasExtension("GL_EXT_packed_depth_stencil") ||
306 ctxInfo.hasExtension("GL_ARB_framebuffer_object");
307
308 // S1 thru S16 formats are in GL 3.0+, EXT_FBO, and ARB_FBO since we
309 // require FBO support we can expect these are legal formats and don't
310 // check. These also all support the unsized GL_STENCIL_INDEX.
311 fStencilFormats.push_back() = gS8;
312 fStencilFormats.push_back() = gS16;
313 if (supportsPackedDS) {
314 fStencilFormats.push_back() = gD24S8;
315 }
316 fStencilFormats.push_back() = gS4;
317 if (supportsPackedDS) {
318 fStencilFormats.push_back() = gDS;
319 }
320 } else {
321 // ES2 has STENCIL_INDEX8 without extensions but requires extensions
322 // for other formats.
323 // ES doesn't support using the unsized format.
324
325 fStencilFormats.push_back() = gS8;
326 //fStencilFormats.push_back() = gS16;
327 if (ctxInfo.hasExtension("GL_OES_packed_depth_stencil")) {
328 fStencilFormats.push_back() = gD24S8;
329 }
330 if (ctxInfo.hasExtension("GL_OES_stencil4")) {
331 fStencilFormats.push_back() = gS4;
332 }
333 }
334 GrAssert(0 == fStencilVerifiedColorConfigs.count());
335 fStencilVerifiedColorConfigs.push_back_n(fStencilFormats.count());
336}
337
338void GrGLCaps::markColorConfigAndStencilFormatAsVerified(
339 GrPixelConfig config,
340 const GrGLStencilBuffer::Format& format) {
341#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT
342 return;
343#endif
344 GrAssert((unsigned)config < kGrPixelConfigCount);
345 GrAssert(fStencilFormats.count() == fStencilVerifiedColorConfigs.count());
346 int count = fStencilFormats.count();
347 // we expect a really small number of possible formats so linear search
348 // should be OK
349 GrAssert(count < 16);
350 for (int i = 0; i < count; ++i) {
351 if (format.fInternalFormat ==
352 fStencilFormats[i].fInternalFormat) {
353 fStencilVerifiedColorConfigs[i].markVerified(config);
354 return;
355 }
356 }
357 GrCrash("Why are we seeing a stencil format that "
358 "GrGLCaps doesn't know about.");
359}
360
361bool GrGLCaps::isColorConfigAndStencilFormatVerified(
362 GrPixelConfig config,
363 const GrGLStencilBuffer::Format& format) const {
364#if !GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT
365 return false;
366#endif
367 GrAssert((unsigned)config < kGrPixelConfigCount);
368 int count = fStencilFormats.count();
369 // we expect a really small number of possible formats so linear search
370 // should be OK
371 GrAssert(count < 16);
372 for (int i = 0; i < count; ++i) {
373 if (format.fInternalFormat ==
374 fStencilFormats[i].fInternalFormat) {
375 return fStencilVerifiedColorConfigs[i].isVerified(config);
376 }
377 }
378 GrCrash("Why are we seeing a stencil format that "
379 "GLCaps doesn't know about.");
380 return false;
381}
382
383void GrGLCaps::print() const {
384 for (int i = 0; i < fStencilFormats.count(); ++i) {
385 GrPrintf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n",
386 i,
387 fStencilFormats[i].fStencilBits,
388 fStencilFormats[i].fTotalBits);
389 }
390
391 GR_STATIC_ASSERT(0 == kNone_MSFBOType);
392 GR_STATIC_ASSERT(1 == kDesktopARB_MSFBOType);
393 GR_STATIC_ASSERT(2 == kDesktopEXT_MSFBOType);
394 GR_STATIC_ASSERT(3 == kAppleES_MSFBOType);
395 static const char* gMSFBOExtStr[] = {
396 "None",
397 "ARB",
398 "EXT",
399 "Apple",
400 };
401 GrPrintf("MSAA Type: %s\n", gMSFBOExtStr[fMSFBOType]);
402 GrPrintf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
403 GrPrintf("Support RGBA8 Render Buffer: %s\n",
404 (fRGBA8RenderbufferSupport ? "YES": "NO"));
405 GrPrintf("BGRA is an internal format: %s\n",
406 (fBGRAIsInternalFormat ? "YES": "NO"));
407 GrPrintf("Support texture swizzle: %s\n",
408 (fTextureSwizzleSupport ? "YES": "NO"));
409 GrPrintf("Unpack Row length support: %s\n",
410 (fUnpackRowLengthSupport ? "YES": "NO"));
411 GrPrintf("Unpack Flip Y support: %s\n",
412 (fUnpackFlipYSupport ? "YES": "NO"));
413 GrPrintf("Pack Row length support: %s\n",
414 (fPackRowLengthSupport ? "YES": "NO"));
415 GrPrintf("Pack Flip Y support: %s\n",
416 (fPackFlipYSupport ? "YES": "NO"));
robertphillips@google.com1d89c932012-06-27 19:31:41 +0000417 GrPrintf("Two Format Limit: %s\n", (fTwoFormatLimit ? "YES": "NO"));
bsalomon@google.comf7fa8062012-02-14 14:09:57 +0000418}
419