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