xref: /third_party/skia/src/gpu/GrCaps.cpp (revision cb93a386)
1/*
2 * Copyright 2015 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#include "src/gpu/GrCaps.h"
9
10#include "include/gpu/GrBackendSurface.h"
11#include "include/gpu/GrContextOptions.h"
12#include "include/private/GrTypesPriv.h"
13#include "src/gpu/GrBackendUtils.h"
14#include "src/gpu/GrRenderTargetProxy.h"
15#include "src/gpu/GrSurface.h"
16#include "src/gpu/GrSurfaceProxy.h"
17#include "src/gpu/GrWindowRectangles.h"
18
19GrCaps::GrCaps(const GrContextOptions& options) {
20    fMipmapSupport = false;
21    fNPOTTextureTileSupport = false;
22    fReuseScratchTextures = true;
23    fReuseScratchBuffers = true;
24    fGpuTracingSupport = false;
25    fOversizedStencilSupport = false;
26    fTextureBarrierSupport = false;
27    fSampleLocationsSupport = false;
28    fDrawInstancedSupport = false;
29    fNativeDrawIndirectSupport = false;
30    fUseClientSideIndirectBuffers = false;
31    fConservativeRasterSupport = false;
32    fWireframeSupport = false;
33    fMSAAResolvesAutomatically = false;
34    fUsePrimitiveRestart = false;
35    fPreferClientSideDynamicBuffers = false;
36    fPreferFullscreenClears = false;
37    fTwoSidedStencilRefsAndMasksMustMatch = false;
38    fMustClearUploadedBufferData = false;
39    fShouldInitializeTextures = false;
40    fSupportsAHardwareBufferImages = false;
41    fFenceSyncSupport = false;
42    fSemaphoreSupport = false;
43    fCrossContextTextureSupport = false;
44    fHalfFloatVertexAttributeSupport = false;
45    fDynamicStateArrayGeometryProcessorTextureSupport = false;
46    fPerformPartialClearsAsDraws = false;
47    fPerformColorClearsAsDraws = false;
48    fAvoidLargeIndexBufferDraws = false;
49    fPerformStencilClearsAsDraws = false;
50    fTransferFromBufferToTextureSupport = false;
51    fTransferFromSurfaceToBufferSupport = false;
52    fWritePixelsRowBytesSupport = false;
53    fTransferPixelsToRowBytesSupport = false;
54    fReadPixelsRowBytesSupport = false;
55    fShouldCollapseSrcOverToSrcWhenAble = false;
56    fMustSyncGpuDuringAbandon = true;
57    fDriverDisableMSAAClipAtlas = false;
58    fDisableTessellationPathRenderer = false;
59
60    fBlendEquationSupport = kBasic_BlendEquationSupport;
61    fAdvBlendEqDisableFlags = 0;
62
63    fMapBufferFlags = kNone_MapFlags;
64
65    fMaxVertexAttributes = 0;
66    fMaxRenderTargetSize = 1;
67    fMaxPreferredRenderTargetSize = 1;
68    fMaxTextureSize = 1;
69    fMaxWindowRectangles = 0;
70    fInternalMultisampleCount = 0;
71
72    fSuppressPrints = options.fSuppressPrints;
73#if GR_TEST_UTILS
74    fWireframeMode = options.fWireframeMode;
75#else
76    fWireframeMode = false;
77#endif
78    fBufferMapThreshold = options.fBufferMapThreshold;
79    fAvoidStencilBuffers = false;
80    fAvoidWritePixelsFastPath = false;
81    fRequiresManualFBBarrierAfterTessellatedStencilDraw = false;
82    fNativeDrawIndexedIndirectIsBroken = false;
83    fAvoidReorderingRenderTasks = false;
84    fAvoidDithering = false;
85
86    fPreferVRAMUseOverFlushes = true;
87
88    // Default to true, allow older versions of OpenGL to disable explicitly
89    fClampToBorderSupport = true;
90
91    fDriverBugWorkarounds = options.fDriverBugWorkarounds;
92}
93
94void GrCaps::finishInitialization(const GrContextOptions& options) {
95    if (!fNativeDrawIndirectSupport) {
96        // We will implement indirect draws with a polyfill, so the commands need to reside in CPU
97        // memory.
98        fUseClientSideIndirectBuffers = true;
99    }
100
101    this->applyOptionsOverrides(options);
102
103    // Our render targets are always created with textures as the color attachment, hence this min:
104    fMaxRenderTargetSize = std::min(fMaxRenderTargetSize, fMaxTextureSize);
105    fMaxPreferredRenderTargetSize = std::min(fMaxPreferredRenderTargetSize, fMaxRenderTargetSize);
106}
107
108void GrCaps::applyOptionsOverrides(const GrContextOptions& options) {
109    fShaderCaps->applyOptionsOverrides(options);
110    this->onApplyOptionsOverrides(options);
111    if (options.fDisableDriverCorrectnessWorkarounds) {
112        SkASSERT(!fDriverDisableMSAAClipAtlas);
113        SkASSERT(!fDisableTessellationPathRenderer);
114        SkASSERT(!fAvoidStencilBuffers);
115        SkASSERT(!fAvoidWritePixelsFastPath);
116        SkASSERT(!fRequiresManualFBBarrierAfterTessellatedStencilDraw);
117        SkASSERT(!fNativeDrawIndexedIndirectIsBroken);
118        SkASSERT(!fAdvBlendEqDisableFlags);
119        SkASSERT(!fPerformColorClearsAsDraws);
120        SkASSERT(!fPerformStencilClearsAsDraws);
121        // Don't check the partial-clear workaround, since that is a backend limitation, not a
122        // driver workaround (it just so happens the fallbacks are the same).
123    }
124    if (GrContextOptions::Enable::kNo == options.fUseDrawInsteadOfClear) {
125        fPerformColorClearsAsDraws = false;
126        fPerformStencilClearsAsDraws = false;
127    } else if (GrContextOptions::Enable::kYes == options.fUseDrawInsteadOfClear) {
128        fPerformColorClearsAsDraws = true;
129        fPerformStencilClearsAsDraws = true;
130    }
131
132    fMaxTextureSize = std::min(fMaxTextureSize, options.fMaxTextureSizeOverride);
133#if GR_TEST_UTILS
134    if (options.fSuppressAdvancedBlendEquations) {
135        fBlendEquationSupport = kBasic_BlendEquationSupport;
136    }
137    if (options.fClearAllTextures) {
138        fShouldInitializeTextures = true;
139    }
140    if (options.fDisallowWriteAndTransferPixelRowBytes) {
141        fWritePixelsRowBytesSupport = false;
142        fTransferPixelsToRowBytesSupport = false;
143    }
144    if (options.fAlwaysPreferHardwareTessellation) {
145        fMinPathVerbsForHwTessellation = fMinStrokeVerbsForHwTessellation = 0;
146    }
147#endif
148    if (options.fSuppressMipmapSupport) {
149        fMipmapSupport = false;
150    }
151
152    if (fMaxWindowRectangles > GrWindowRectangles::kMaxWindows) {
153        SkDebugf("WARNING: capping window rectangles at %i. HW advertises support for %i.\n",
154                 GrWindowRectangles::kMaxWindows, fMaxWindowRectangles);
155        fMaxWindowRectangles = GrWindowRectangles::kMaxWindows;
156    }
157
158    fInternalMultisampleCount = options.fInternalMultisampleCount;
159
160    fAvoidStencilBuffers = options.fAvoidStencilBuffers;
161
162    fDriverBugWorkarounds.applyOverrides(options.fDriverBugWorkarounds);
163}
164
165
166#ifdef SK_ENABLE_DUMP_GPU
167#include "src/gpu/GrTestUtils.h"
168#include "src/utils/SkJSONWriter.h"
169
170static SkString map_flags_to_string(uint32_t flags) {
171    SkString str;
172    if (GrCaps::kNone_MapFlags == flags) {
173        str = "none";
174    } else {
175        SkASSERT(GrCaps::kCanMap_MapFlag & flags);
176        SkDEBUGCODE(flags &= ~GrCaps::kCanMap_MapFlag);
177        str = "can_map";
178
179        if (GrCaps::kSubset_MapFlag & flags) {
180            str.append(" partial");
181        } else {
182            str.append(" full");
183        }
184        SkDEBUGCODE(flags &= ~GrCaps::kSubset_MapFlag);
185        if (GrCaps::kAsyncRead_MapFlag & flags) {
186            str.append(" async_read");
187        } else {
188            str.append(" sync_read");
189        }
190        SkDEBUGCODE(flags &= ~GrCaps::kAsyncRead_MapFlag);
191    }
192    SkASSERT(0 == flags); // Make sure we handled all the flags.
193    return str;
194}
195
196void GrCaps::dumpJSON(SkJSONWriter* writer) const {
197    writer->beginObject();
198
199    writer->appendBool("MIP Map Support", fMipmapSupport);
200    writer->appendBool("NPOT Texture Tile Support", fNPOTTextureTileSupport);
201    writer->appendBool("Reuse Scratch Textures", fReuseScratchTextures);
202    writer->appendBool("Reuse Scratch Buffers", fReuseScratchBuffers);
203    writer->appendBool("Gpu Tracing Support", fGpuTracingSupport);
204    writer->appendBool("Oversized Stencil Support", fOversizedStencilSupport);
205    writer->appendBool("Texture Barrier Support", fTextureBarrierSupport);
206    writer->appendBool("Sample Locations Support", fSampleLocationsSupport);
207    writer->appendBool("Draw Instanced Support", fDrawInstancedSupport);
208    writer->appendBool("Native Draw Indirect Support", fNativeDrawIndirectSupport);
209    writer->appendBool("Use client side indirect buffers", fUseClientSideIndirectBuffers);
210    writer->appendBool("Conservative Raster Support", fConservativeRasterSupport);
211    writer->appendBool("Wireframe Support", fWireframeSupport);
212    writer->appendBool("MSAA Resolves Automatically", fMSAAResolvesAutomatically);
213    writer->appendBool("Use primitive restart", fUsePrimitiveRestart);
214    writer->appendBool("Prefer client-side dynamic buffers", fPreferClientSideDynamicBuffers);
215    writer->appendBool("Prefer fullscreen clears (and stencil discard)", fPreferFullscreenClears);
216    writer->appendBool("Two-sided Stencil Refs And Masks Must Match",
217                       fTwoSidedStencilRefsAndMasksMustMatch);
218    writer->appendBool("Must clear buffer memory", fMustClearUploadedBufferData);
219    writer->appendBool("Should initialize textures", fShouldInitializeTextures);
220    writer->appendBool("Supports importing AHardwareBuffers", fSupportsAHardwareBufferImages);
221    writer->appendBool("Fence sync support", fFenceSyncSupport);
222    writer->appendBool("Semaphore support", fSemaphoreSupport);
223    writer->appendBool("Cross context texture support", fCrossContextTextureSupport);
224    writer->appendBool("Half float vertex attribute support", fHalfFloatVertexAttributeSupport);
225    writer->appendBool("Specify GeometryProcessor textures as a dynamic state array",
226                       fDynamicStateArrayGeometryProcessorTextureSupport);
227    writer->appendBool("Use draws for partial clears", fPerformPartialClearsAsDraws);
228    writer->appendBool("Use draws for color clears", fPerformColorClearsAsDraws);
229    writer->appendBool("Avoid Large IndexBuffer Draws", fAvoidLargeIndexBufferDraws);
230    writer->appendBool("Use draws for stencil clip clears", fPerformStencilClearsAsDraws);
231    writer->appendBool("Supports transfers from buffers to textures",
232                       fTransferFromBufferToTextureSupport);
233    writer->appendBool("Supports transfers from textures to buffers",
234                       fTransferFromSurfaceToBufferSupport);
235    writer->appendBool("Write pixels row bytes support", fWritePixelsRowBytesSupport);
236    writer->appendBool("Transfer pixels to row bytes support", fTransferPixelsToRowBytesSupport);
237    writer->appendBool("Read pixels row bytes support", fReadPixelsRowBytesSupport);
238    writer->appendBool("Disable msaa clip mask atlas on current driver [workaround]",
239                       fDriverDisableMSAAClipAtlas);
240    writer->appendBool("Disable TessellationPathRenderer current driver [workaround]",
241                       fDisableTessellationPathRenderer);
242    writer->appendBool("Clamp-to-border", fClampToBorderSupport);
243
244    writer->appendBool("Prefer VRAM Use over flushes [workaround]", fPreferVRAMUseOverFlushes);
245    writer->appendBool("Avoid stencil buffers [workaround]", fAvoidStencilBuffers);
246    writer->appendBool("Avoid writePixels fast path [workaround]", fAvoidWritePixelsFastPath);
247    writer->appendBool("Requires manual FB barrier after tessellated stencilDraw [workaround]",
248                       fRequiresManualFBBarrierAfterTessellatedStencilDraw);
249    writer->appendBool("Native draw indexed indirect is broken [workaround]",
250                       fNativeDrawIndexedIndirectIsBroken);
251    writer->appendBool("Avoid DAG reordering [workaround]", fAvoidReorderingRenderTasks);
252    writer->appendBool("Avoid Dithering [workaround]", fAvoidDithering);
253
254    if (this->advancedBlendEquationSupport()) {
255        writer->appendHexU32("Advanced Blend Equation Disable Flags", fAdvBlendEqDisableFlags);
256    }
257
258    writer->appendS32("Max Vertex Attributes", fMaxVertexAttributes);
259    writer->appendS32("Max Texture Size", fMaxTextureSize);
260    writer->appendS32("Max Render Target Size", fMaxRenderTargetSize);
261    writer->appendS32("Max Preferred Render Target Size", fMaxPreferredRenderTargetSize);
262    writer->appendS32("Max Window Rectangles", fMaxWindowRectangles);
263    writer->appendS32("Sample Count for Internal MSAA", fInternalMultisampleCount);
264    writer->appendS32("Min Path Verbs for HW Tessellation", fMinPathVerbsForHwTessellation);
265    writer->appendS32("Min Stroke Verbs for HW Tessellation", fMinStrokeVerbsForHwTessellation);
266
267    static const char* kBlendEquationSupportNames[] = {
268        "Basic",
269        "Advanced",
270        "Advanced Coherent",
271    };
272    static_assert(0 == kBasic_BlendEquationSupport);
273    static_assert(1 == kAdvanced_BlendEquationSupport);
274    static_assert(2 == kAdvancedCoherent_BlendEquationSupport);
275    static_assert(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1);
276
277    writer->appendString("Blend Equation Support",
278                         kBlendEquationSupportNames[fBlendEquationSupport]);
279    writer->appendString("Map Buffer Support", map_flags_to_string(fMapBufferFlags).c_str());
280
281    this->onDumpJSON(writer);
282
283    writer->appendName("shaderCaps");
284    this->shaderCaps()->dumpJSON(writer);
285
286    writer->endObject();
287}
288#else
289void GrCaps::dumpJSON(SkJSONWriter* writer) const { }
290#endif
291
292bool GrCaps::surfaceSupportsWritePixels(const GrSurface* surface) const {
293    return surface->readOnly() ? false : this->onSurfaceSupportsWritePixels(surface);
294}
295
296bool GrCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
297                            const SkIRect& srcRect, const SkIPoint& dstPoint) const {
298    if (dst->readOnly()) {
299        return false;
300    }
301
302    if (dst->backendFormat() != src->backendFormat()) {
303        return false;
304    }
305    return this->onCanCopySurface(dst, src, srcRect, dstPoint);
306}
307
308bool GrCaps::validateSurfaceParams(const SkISize& dimensions, const GrBackendFormat& format,
309                                   GrRenderable renderable, int renderTargetSampleCnt,
310                                   GrMipmapped mipped, GrTextureType textureType) const {
311    if (textureType != GrTextureType::kNone) {
312        if (!this->isFormatTexturable(format, textureType)) {
313            return false;
314        }
315    }
316
317    if (GrMipmapped::kYes == mipped && !this->mipmapSupport()) {
318        return false;
319    }
320
321    if (dimensions.width() < 1 || dimensions.height() < 1) {
322        return false;
323    }
324
325    if (renderable == GrRenderable::kYes) {
326        if (!this->isFormatRenderable(format, renderTargetSampleCnt)) {
327            return false;
328        }
329        int maxRTSize = this->maxRenderTargetSize();
330        if (dimensions.width() > maxRTSize || dimensions.height() > maxRTSize) {
331            return false;
332        }
333    } else {
334        // We currently do not support multisampled textures
335        if (renderTargetSampleCnt != 1) {
336            return false;
337        }
338        int maxSize = this->maxTextureSize();
339        if (dimensions.width() > maxSize || dimensions.height() > maxSize) {
340            return false;
341        }
342    }
343
344    return true;
345}
346
347GrCaps::SupportedRead GrCaps::supportedReadPixelsColorType(GrColorType srcColorType,
348                                                           const GrBackendFormat& srcFormat,
349                                                           GrColorType dstColorType) const {
350    SupportedRead read = this->onSupportedReadPixelsColorType(srcColorType, srcFormat,
351                                                              dstColorType);
352
353    // There are known problems with 24 vs 32 bit BPP with this color type. Just fail for now if
354    // using a transfer buffer.
355    if (GrColorType::kRGB_888x == read.fColorType) {
356        read.fOffsetAlignmentForTransferBuffer = 0;
357    }
358    // It's very convenient to access 1 byte-per-channel 32 bit color types as uint32_t on the CPU.
359    // Make those aligned reads out of the buffer even if the underlying API doesn't require it.
360    auto channelFlags = GrColorTypeChannelFlags(read.fColorType);
361    if ((channelFlags == kRGBA_SkColorChannelFlags || channelFlags == kRGB_SkColorChannelFlags ||
362         channelFlags == kAlpha_SkColorChannelFlag || channelFlags == kGray_SkColorChannelFlag) &&
363        GrColorTypeBytesPerPixel(read.fColorType) == 4) {
364        switch (read.fOffsetAlignmentForTransferBuffer & 0b11) {
365            // offset alignment already a multiple of 4
366            case 0:
367                break;
368            // offset alignment is a multiple of 2 but not 4.
369            case 2:
370                read.fOffsetAlignmentForTransferBuffer *= 2;
371                break;
372            // offset alignment is not a multiple of 2.
373            default:
374                read.fOffsetAlignmentForTransferBuffer *= 4;
375                break;
376        }
377    }
378    return read;
379}
380
381GrBackendFormat GrCaps::getDefaultBackendFormat(GrColorType colorType,
382                                                GrRenderable renderable) const {
383    // Unknown color types are always an invalid format, so early out before calling virtual.
384    if (colorType == GrColorType::kUnknown) {
385        return {};
386    }
387
388    auto format = this->onGetDefaultBackendFormat(colorType);
389    if (!this->isFormatTexturable(format, GrTextureType::k2D)) {
390        return {};
391    }
392    if (!this->areColorTypeAndFormatCompatible(colorType, format)) {
393        return {};
394    }
395    // Currently we require that it be possible to write pixels into the "default" format. Perhaps,
396    // that could be a separate requirement from the caller. It seems less necessary if
397    // renderability was requested.
398    if (this->supportedWritePixelsColorType(colorType, format, colorType).fColorType ==
399        GrColorType::kUnknown) {
400        return {};
401    }
402    if (renderable == GrRenderable::kYes &&
403        !this->isFormatAsColorTypeRenderable(colorType, format)) {
404        return {};
405    }
406    return format;
407}
408
409bool GrCaps::areColorTypeAndFormatCompatible(GrColorType grCT,
410                                             const GrBackendFormat& format) const {
411    if (GrColorType::kUnknown == grCT) {
412        return false;
413    }
414
415    SkImage::CompressionType compression = GrBackendFormatToCompressionType(format);
416    if (compression != SkImage::CompressionType::kNone) {
417        return grCT == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
418                                                               : GrColorType::kRGBA_8888);
419    }
420
421    return this->onAreColorTypeAndFormatCompatible(grCT, format);
422}
423
424GrSwizzle GrCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
425    SkImage::CompressionType compression = GrBackendFormatToCompressionType(format);
426    if (compression != SkImage::CompressionType::kNone) {
427        if (colorType == GrColorType::kRGB_888x || colorType == GrColorType::kRGBA_8888) {
428            return GrSwizzle::RGBA();
429        }
430        SkDEBUGFAILF("Illegal color type (%d) and compressed format (%d) combination.",
431                     (int)colorType, (int)compression);
432        return {};
433    }
434
435    return this->onGetReadSwizzle(format, colorType);
436}
437
438bool GrCaps::isFormatCompressed(const GrBackendFormat& format) const {
439    return GrBackendFormatToCompressionType(format) != SkImage::CompressionType::kNone;
440}
441
442GrDstSampleFlags GrCaps::getDstSampleFlagsForProxy(const GrRenderTargetProxy* rt,
443                                                   bool drawUsesMSAA) const {
444    SkASSERT(rt);
445    if (this->textureBarrierSupport() && (!drawUsesMSAA || this->msaaResolvesAutomatically())) {
446        return this->onGetDstSampleFlagsForProxy(rt);
447    }
448    return GrDstSampleFlags::kNone;
449}
450
451bool GrCaps::supportsDynamicMSAA(const GrRenderTargetProxy* rtProxy) const {
452    return rtProxy->numSamples() == 1 &&
453           this->internalMultisampleCount(rtProxy->backendFormat()) > 1 &&
454           this->onSupportsDynamicMSAA(rtProxy);
455}
456
457static inline GrColorType color_type_fallback(GrColorType ct) {
458    switch (ct) {
459        // kRGBA_8888 is our default fallback for many color types that may not have renderable
460        // backend formats.
461        case GrColorType::kAlpha_8:
462        case GrColorType::kBGR_565:
463        case GrColorType::kABGR_4444:
464        case GrColorType::kBGRA_8888:
465        case GrColorType::kRGBA_1010102:
466        case GrColorType::kBGRA_1010102:
467        case GrColorType::kRGBA_F16:
468        case GrColorType::kRGBA_F16_Clamped:
469            return GrColorType::kRGBA_8888;
470        case GrColorType::kAlpha_F16:
471            return GrColorType::kRGBA_F16;
472        case GrColorType::kGray_8:
473            return GrColorType::kRGB_888x;
474        default:
475            return GrColorType::kUnknown;
476    }
477}
478
479std::tuple<GrColorType, GrBackendFormat> GrCaps::getFallbackColorTypeAndFormat(
480                                                                            GrColorType ct,
481                                                                            int sampleCnt) const {
482    do {
483        auto format = this->getDefaultBackendFormat(ct, GrRenderable::kYes);
484        // We continue to the fallback color type if there no default renderable format or we
485        // requested msaa and the format doesn't support msaa.
486        if (format.isValid() && this->isFormatRenderable(format, sampleCnt)) {
487            return {ct, format};
488        }
489        ct = color_type_fallback(ct);
490    } while (ct != GrColorType::kUnknown);
491    return {GrColorType::kUnknown, {}};
492}
493