GrGLCaps.cpp revision eca2dfb002888e4af590275a6da3f157ebb6473b
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
13GrGLCaps::GrGLCaps() {
14    this->reset();
15}
16
17void 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}
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;
50    fMaxVertexAttributes = caps.fMaxVertexAttributes;
51    fMSFBOType = caps.fMSFBOType;
52    fMaxSampleCount = caps.fMaxSampleCount;
53    fCoverageAAType = caps.fCoverageAAType;
54    fMSAACoverageModes = caps.fMSAACoverageModes;
55    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;
65    fTextureRedSupport = caps.fTextureRedSupport;
66    fImagingSupport = caps.fImagingSupport;
67    fTwoFormatLimit = caps.fTwoFormatLimit;
68
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    }
92    GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttributes);
93
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 {
105        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 ||
112                 kSkia8888_PM_GrPixelConfig != kBGRA_8888_PM_GrPixelConfig);
113    }
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
145    // 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
153    fImagingSupport = kDesktop_GrGLBinding == binding &&
154                      ctxInfo.hasExtension("GL_ARB_imaging");
155
156    // 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
161    this->initFSAASupport(ctxInfo);
162    this->initStencilFormats(ctxInfo);
163}
164
165bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf,
166                                   GrGLenum format,
167                                   GrGLenum type) const {
168    if (GR_GL_RGBA == format && GR_GL_UNSIGNED_BYTE == type) {
169        // ES 2 guarantees this format is supported
170        return true;
171    }
172
173    if (!fTwoFormatLimit) {
174        // not limited by ES 2's constraints
175        return true;
176    }
177
178    int otherFormat = GR_GL_RGBA;
179    int otherType = GR_GL_UNSIGNED_BYTE;
180
181    // The other supported format/type combo supported for ReadPixels
182    // can change based on which render target is bound
183    GR_GL_GetIntegerv(intf,
184                      GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT,
185                      &otherFormat);
186
187    GR_GL_GetIntegerv(intf,
188                      GR_GL_IMPLEMENTATION_COLOR_READ_TYPE,
189                      &otherType);
190
191    return otherFormat == format && otherType == type;
192}
193
194namespace {
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
210void 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")) {
219           fMSFBOType = kAppleES_MSFBOType;
220       }
221    } 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        }
229        // 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.
245            qsort(&fMSAACoverageModes[0],
246                    count,
247                    sizeof(MSAACoverageMode),
248                    SkCastForQSort(coverage_mode_compare));
249        }
250    }
251    if (kNone_MSFBOType != fMSFBOType) {
252        GR_GL_GetIntegerv(ctxInfo.interface(),
253                          GR_GL_MAX_SAMPLES,
254                          &fMaxSampleCount);
255    }
256}
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];
278    }
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},
299    //  gS     = {GR_GL_STENCIL_INDEX,    kUnknownBitCount, kUnknownBitCount, false},
300        gDS    = {GR_GL_DEPTH_STENCIL,    kUnknownBitCount, kUnknownBitCount, true };
301
302    if (kDesktop_GrGLBinding == ctxInfo.binding()) {
303        bool supportsPackedDS =
304            ctxInfo.version() >= GR_GL_VER(3,0) ||
305            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"));
417    GrPrintf("Two Format Limit: %s\n", (fTwoFormatLimit ? "YES": "NO"));
418}
419
420