1 
2 /*
3  * Copyright 2013 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #ifndef GrCaps_DEFINED
9 #define GrCaps_DEFINED
10 
11 #include "../private/GrTypesPriv.h"
12 #include "GrBlend.h"
13 #include "GrDriverBugWorkarounds.h"
14 #include "GrShaderCaps.h"
15 #include "SkImageInfo.h"
16 #include "SkRefCnt.h"
17 #include "SkString.h"
18 
19 class GrBackendFormat;
20 class GrBackendRenderTarget;
21 class GrBackendTexture;
22 struct GrContextOptions;
23 class GrRenderTargetProxy;
24 class GrSurface;
25 class GrSurfaceProxy;
26 class SkJSONWriter;
27 
28 /**
29  * Represents the capabilities of a GrContext.
30  */
31 class GrCaps : public SkRefCnt {
32 public:
33     GrCaps(const GrContextOptions&);
34 
35     void dumpJSON(SkJSONWriter*) const;
36 
shaderCaps()37     const GrShaderCaps* shaderCaps() const { return fShaderCaps.get(); }
38 
npotTextureTileSupport()39     bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; }
40     /** To avoid as-yet-unnecessary complexity we don't allow any partial support of MIP Maps (e.g.
41         only for POT textures) */
mipMapSupport()42     bool mipMapSupport() const { return fMipMapSupport; }
43 
44     /**
45      * Skia convention is that a device only has sRGB support if it supports sRGB formats for both
46      * textures and framebuffers.
47      */
srgbSupport()48     bool srgbSupport() const { return fSRGBSupport; }
49     /**
50      * Is there support for enabling/disabling sRGB writes for sRGB-capable color buffers?
51      */
srgbWriteControl()52     bool srgbWriteControl() const { return fSRGBWriteControl; }
discardRenderTargetSupport()53     bool discardRenderTargetSupport() const { return fDiscardRenderTargetSupport; }
gpuTracingSupport()54     bool gpuTracingSupport() const { return fGpuTracingSupport; }
compressedTexSubImageSupport()55     bool compressedTexSubImageSupport() const { return fCompressedTexSubImageSupport; }
oversizedStencilSupport()56     bool oversizedStencilSupport() const { return fOversizedStencilSupport; }
textureBarrierSupport()57     bool textureBarrierSupport() const { return fTextureBarrierSupport; }
sampleLocationsSupport()58     bool sampleLocationsSupport() const { return fSampleLocationsSupport; }
multisampleDisableSupport()59     bool multisampleDisableSupport() const { return fMultisampleDisableSupport; }
instanceAttribSupport()60     bool instanceAttribSupport() const { return fInstanceAttribSupport; }
usesMixedSamples()61     bool usesMixedSamples() const { return fUsesMixedSamples; }
halfFloatVertexAttributeSupport()62     bool halfFloatVertexAttributeSupport() const { return fHalfFloatVertexAttributeSupport; }
63 
64     // Primitive restart functionality is core in ES 3.0, but using it will cause slowdowns on some
65     // systems. This cap is only set if primitive restart will improve performance.
usePrimitiveRestart()66     bool usePrimitiveRestart() const { return fUsePrimitiveRestart; }
67 
preferClientSideDynamicBuffers()68     bool preferClientSideDynamicBuffers() const { return fPreferClientSideDynamicBuffers; }
69 
70     // On tilers, an initial fullscreen clear is an OPTIMIZATION. It allows the hardware to
71     // initialize each tile with a constant value rather than loading each pixel from memory.
preferFullscreenClears()72     bool preferFullscreenClears() const { return fPreferFullscreenClears; }
73 
preferVRAMUseOverFlushes()74     bool preferVRAMUseOverFlushes() const { return fPreferVRAMUseOverFlushes; }
75 
blacklistCoverageCounting()76     bool blacklistCoverageCounting() const { return fBlacklistCoverageCounting; }
77 
avoidStencilBuffers()78     bool avoidStencilBuffers() const { return fAvoidStencilBuffers; }
79 
avoidWritePixelsFastPath()80     bool avoidWritePixelsFastPath() const { return fAvoidWritePixelsFastPath; }
81 
82     /**
83      * Indicates the capabilities of the fixed function blend unit.
84      */
85     enum BlendEquationSupport {
86         kBasic_BlendEquationSupport,             //<! Support to select the operator that
87                                                  //   combines src and dst terms.
88         kAdvanced_BlendEquationSupport,          //<! Additional fixed function support for specific
89                                                  //   SVG/PDF blend modes. Requires blend barriers.
90         kAdvancedCoherent_BlendEquationSupport,  //<! Advanced blend equation support that does not
91                                                  //   require blend barriers, and permits overlap.
92 
93         kLast_BlendEquationSupport = kAdvancedCoherent_BlendEquationSupport
94     };
95 
blendEquationSupport()96     BlendEquationSupport blendEquationSupport() const { return fBlendEquationSupport; }
97 
advancedBlendEquationSupport()98     bool advancedBlendEquationSupport() const {
99         return fBlendEquationSupport >= kAdvanced_BlendEquationSupport;
100     }
101 
advancedCoherentBlendEquationSupport()102     bool advancedCoherentBlendEquationSupport() const {
103         return kAdvancedCoherent_BlendEquationSupport == fBlendEquationSupport;
104     }
105 
isAdvancedBlendEquationBlacklisted(GrBlendEquation equation)106     bool isAdvancedBlendEquationBlacklisted(GrBlendEquation equation) const {
107         SkASSERT(GrBlendEquationIsAdvanced(equation));
108         SkASSERT(this->advancedBlendEquationSupport());
109         return SkToBool(fAdvBlendEqBlacklist & (1 << equation));
110     }
111 
112     /**
113      * Indicates whether GPU->CPU memory mapping for GPU resources such as vertex buffers and
114      * textures allows partial mappings or full mappings.
115      */
116     enum MapFlags {
117         kNone_MapFlags   = 0x0,       //<! Cannot map the resource.
118 
119         kCanMap_MapFlag  = 0x1,       //<! The resource can be mapped. Must be set for any of
120                                       //   the other flags to have meaning.
121         kSubset_MapFlag  = 0x2,       //<! The resource can be partially mapped.
122     };
123 
mapBufferFlags()124     uint32_t mapBufferFlags() const { return fMapBufferFlags; }
125 
126     // Scratch textures not being reused means that those scratch textures
127     // that we upload to (i.e., don't have a render target) will not be
128     // recycled in the texture cache. This is to prevent ghosting by drivers
129     // (in particular for deferred architectures).
reuseScratchTextures()130     bool reuseScratchTextures() const { return fReuseScratchTextures; }
reuseScratchBuffers()131     bool reuseScratchBuffers() const { return fReuseScratchBuffers; }
132 
133     /// maximum number of attribute values per vertex
maxVertexAttributes()134     int maxVertexAttributes() const { return fMaxVertexAttributes; }
135 
maxRenderTargetSize()136     int maxRenderTargetSize() const { return fMaxRenderTargetSize; }
137 
138     /** This is the largest render target size that can be used without incurring extra perfomance
139         cost. It is usually the max RT size, unless larger render targets are known to be slower. */
maxPreferredRenderTargetSize()140     int maxPreferredRenderTargetSize() const { return fMaxPreferredRenderTargetSize; }
141 
maxTextureSize()142     int maxTextureSize() const { return fMaxTextureSize; }
143 
144     /** This is the maximum tile size to use by GPU devices for rendering sw-backed images/bitmaps.
145         It is usually the max texture size, unless we're overriding it for testing. */
maxTileSize()146     int maxTileSize() const {
147         SkASSERT(fMaxTileSize <= fMaxTextureSize);
148         return fMaxTileSize;
149     }
150 
maxRasterSamples()151     int maxRasterSamples() const { return fMaxRasterSamples; }
152 
maxWindowRectangles()153     int maxWindowRectangles() const { return fMaxWindowRectangles; }
154 
155     // Returns whether mixed samples is supported for the given backend render target.
isWindowRectanglesSupportedForRT(const GrBackendRenderTarget & rt)156     bool isWindowRectanglesSupportedForRT(const GrBackendRenderTarget& rt) const {
157         return this->maxWindowRectangles() > 0 && this->onIsWindowRectanglesSupportedForRT(rt);
158     }
159 
160     // A tuned, platform-specific value for the maximum number of analytic fragment processors we
161     // should use to implement a clip, before falling back on a mask.
maxClipAnalyticFPs()162     int maxClipAnalyticFPs() const { return fMaxClipAnalyticFPs; }
163 
164     virtual bool isConfigTexturable(GrPixelConfig) const = 0;
165 
166     // Returns whether a texture of the given config can be copied to a texture of the same config.
167     virtual bool isConfigCopyable(GrPixelConfig) const = 0;
168 
169     // Returns the maximum supported sample count for a config. 0 means the config is not renderable
170     // 1 means the config is renderable but doesn't support MSAA.
171     virtual int maxRenderTargetSampleCount(GrPixelConfig) const = 0;
172 
isConfigRenderable(GrPixelConfig config)173     bool isConfigRenderable(GrPixelConfig config) const {
174         return this->maxRenderTargetSampleCount(config) > 0;
175     }
176 
177     // TODO: Remove this after Flutter updated to no longer use it.
isConfigRenderable(GrPixelConfig config,bool withMSAA)178     bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
179         return this->maxRenderTargetSampleCount(config) > (withMSAA ? 1 : 0);
180     }
181 
182     // Find a sample count greater than or equal to the requested count which is supported for a
183     // color buffer of the given config or 0 if no such sample count is supported. If the requested
184     // sample count is 1 then 1 will be returned if non-MSAA rendering is supported, otherwise 0.
185     // For historical reasons requestedCount==0 is handled identically to requestedCount==1.
186     virtual int getRenderTargetSampleCount(int requestedCount, GrPixelConfig) const = 0;
187     // TODO: Remove. Legacy name used by Chrome.
getSampleCount(int requestedCount,GrPixelConfig config)188     int getSampleCount(int requestedCount, GrPixelConfig config) const {
189         return this->getRenderTargetSampleCount(requestedCount, config);
190     }
191 
192     /**
193      * Backends may have restrictions on what types of surfaces support GrGpu::writePixels().
194      * If this returns false then the caller should implement a fallback where a temporary texture
195      * is created, pixels are written to it, and then that is copied or drawn into the the surface.
196      */
197     bool surfaceSupportsWritePixels(const GrSurface*) const;
198 
199     /**
200      * Backends may have restrictions on what types of surfaces support GrGpu::readPixels().
201      * If this returns false then the caller should implement a fallback where a temporary texture
202      * is created, the surface is drawn or copied into the temporary, and pixels are read from the
203      * temporary.
204      */
205     virtual bool surfaceSupportsReadPixels(const GrSurface*) const = 0;
206 
207     /**
208      * Given a dst pixel config and a src color type what color type must the caller coax the
209      * the data into in order to use GrGpu::writePixels().
210      */
supportedWritePixelsColorType(GrPixelConfig config,GrColorType)211     virtual GrColorType supportedWritePixelsColorType(GrPixelConfig config,
212                                                       GrColorType /*srcColorType*/) const {
213         return GrPixelConfigToColorType(config);
214     }
215 
216     /**
217      * Given a src pixel config and a dst color type what color type must the caller read to using
218      * GrGpu::readPixels() and then coax into dstColorType.
219      */
supportedReadPixelsColorType(GrPixelConfig config,GrColorType)220     virtual GrColorType supportedReadPixelsColorType(GrPixelConfig config,
221                                                      GrColorType /*dstColorType*/) const {
222         return GrPixelConfigToColorType(config);
223     }
224 
suppressPrints()225     bool suppressPrints() const { return fSuppressPrints; }
226 
bufferMapThreshold()227     size_t bufferMapThreshold() const {
228         SkASSERT(fBufferMapThreshold >= 0);
229         return fBufferMapThreshold;
230     }
231 
232     /** True in environments that will issue errors if memory uploaded to buffers
233         is not initialized (even if not read by draw calls). */
mustClearUploadedBufferData()234     bool mustClearUploadedBufferData() const { return fMustClearUploadedBufferData; }
235 
236     /** Returns true if the given backend supports importing AHardwareBuffers via the
237      * GrAHardwarebufferImageGenerator. This will only ever be supported on Android devices with API
238      * level >= 26.
239      * */
supportsAHardwareBufferImages()240     bool supportsAHardwareBufferImages() const { return fSupportsAHardwareBufferImages; }
241 
wireframeMode()242     bool wireframeMode() const { return fWireframeMode; }
243 
fenceSyncSupport()244     bool fenceSyncSupport() const { return fFenceSyncSupport; }
crossContextTextureSupport()245     bool crossContextTextureSupport() const { return fCrossContextTextureSupport; }
246     /**
247      * Returns whether or not we will be able to do a copy given the passed in params
248      */
249     bool canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
250                         const SkIRect& srcRect, const SkIPoint& dstPoint) const;
251 
dynamicStateArrayGeometryProcessorTextureSupport()252     bool dynamicStateArrayGeometryProcessorTextureSupport() const {
253         return fDynamicStateArrayGeometryProcessorTextureSupport;
254     }
255 
256     // Not all backends support clearing with a scissor test (e.g. Metal), this will always
257     // return true if performColorClearsAsDraws() returns true.
performPartialClearsAsDraws()258     bool performPartialClearsAsDraws() const {
259         return fPerformColorClearsAsDraws || fPerformPartialClearsAsDraws;
260     }
261 
262     // Many drivers have issues with color clears.
performColorClearsAsDraws()263     bool performColorClearsAsDraws() const {
264         return fPerformColorClearsAsDraws;
265     }
266 
267     /// Adreno 4xx devices experience an issue when there are a large number of stencil clip bit
268     /// clears. The minimal repro steps are not precisely known but drawing a rect with a stencil
269     /// op instead of using glClear seems to resolve the issue.
performStencilClearsAsDraws()270     bool performStencilClearsAsDraws() const {
271         return fPerformStencilClearsAsDraws;
272     }
273 
274     /**
275      * This is can be called before allocating a texture to be a dst for copySurface. This is only
276      * used for doing dst copies needed in blends, thus the src is always a GrRenderTargetProxy. It
277      * will populate config and flags fields of the desc such that copySurface can efficiently
278      * succeed as well as the proxy origin. rectsMustMatch will be set to true if the copy operation
279      * must ensure that the src and dest rects are identical. disallowSubrect will be set to true if
280      * copy rect must equal src's bounds.
281      */
282     virtual bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
283                                     GrSurfaceOrigin* origin, bool* rectsMustMatch,
284                                     bool* disallowSubrect) const = 0;
285 
286     bool validateSurfaceDesc(const GrSurfaceDesc&, GrMipMapped) const;
287 
288     /**
289      * If the GrBackendRenderTarget can be used with the supplied SkColorType the return will be
290      * the config that matches the backend format and requested SkColorType. Otherwise, kUnknown is
291      * returned.
292      */
293     virtual GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
294                                                       SkColorType) const = 0;
295 
296     // TODO: replace validateBackendRenderTarget with calls to getConfigFromBackendFormat?
297     // TODO: it seems like we could pass the full SkImageInfo and validate its colorSpace too
298     // Returns kUnknown if a valid config could not be determined.
299     virtual GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat& format,
300                                                      SkColorType ct) const = 0;
301 
302     /**
303      * Special method only for YUVA images. Returns a config that matches the backend format or
304      * kUnknown if a config could not be determined.
305      */
306     virtual GrPixelConfig getYUVAConfigFromBackendFormat(const GrBackendFormat& format) const = 0;
307 
308     /** These are used when creating a new texture internally. */
309     virtual GrBackendFormat getBackendFormatFromGrColorType(GrColorType ct,
310                                                             GrSRGBEncoded srgbEncoded) const = 0;
311     GrBackendFormat getBackendFormatFromColorType(SkColorType ct) const;
312 
313     /**
314      * The CLAMP_TO_BORDER wrap mode for texture coordinates was added to desktop GL in 1.3, and
315      * GLES 3.2, but is also available in extensions. Vulkan and Metal always have support.
316      */
clampToBorderSupport()317     bool clampToBorderSupport() const { return fClampToBorderSupport; }
318 
workarounds()319     const GrDriverBugWorkarounds& workarounds() const { return fDriverBugWorkarounds; }
320 
321 protected:
322     /** Subclasses must call this at the end of their constructors in order to apply caps
323         overrides requested by the client. Note that overrides will only reduce the caps never
324         expand them. */
325     void applyOptionsOverrides(const GrContextOptions& options);
326 
327     sk_sp<GrShaderCaps> fShaderCaps;
328 
329     bool fNPOTTextureTileSupport                     : 1;
330     bool fMipMapSupport                              : 1;
331     bool fSRGBSupport                                : 1;
332     bool fSRGBWriteControl                           : 1;
333     bool fDiscardRenderTargetSupport                 : 1;
334     bool fReuseScratchTextures                       : 1;
335     bool fReuseScratchBuffers                        : 1;
336     bool fGpuTracingSupport                          : 1;
337     bool fCompressedTexSubImageSupport               : 1;
338     bool fOversizedStencilSupport                    : 1;
339     bool fTextureBarrierSupport                      : 1;
340     bool fSampleLocationsSupport                     : 1;
341     bool fMultisampleDisableSupport                  : 1;
342     bool fInstanceAttribSupport                      : 1;
343     bool fUsesMixedSamples                           : 1;
344     bool fUsePrimitiveRestart                        : 1;
345     bool fPreferClientSideDynamicBuffers             : 1;
346     bool fPreferFullscreenClears                     : 1;
347     bool fMustClearUploadedBufferData                : 1;
348     bool fSupportsAHardwareBufferImages              : 1;
349     bool fHalfFloatVertexAttributeSupport            : 1;
350     bool fClampToBorderSupport                       : 1;
351     bool fPerformPartialClearsAsDraws                : 1;
352     bool fPerformColorClearsAsDraws                  : 1;
353     bool fPerformStencilClearsAsDraws                : 1;
354 
355     // Driver workaround
356     bool fBlacklistCoverageCounting                  : 1;
357     bool fAvoidStencilBuffers                        : 1;
358     bool fAvoidWritePixelsFastPath                   : 1;
359 
360     // ANGLE performance workaround
361     bool fPreferVRAMUseOverFlushes                   : 1;
362 
363     // TODO: this may need to be an enum to support different fence types
364     bool fFenceSyncSupport                           : 1;
365 
366     // Requires fence sync support in GL.
367     bool fCrossContextTextureSupport                 : 1;
368 
369     // Not (yet) implemented in VK backend.
370     bool fDynamicStateArrayGeometryProcessorTextureSupport : 1;
371 
372     BlendEquationSupport fBlendEquationSupport;
373     uint32_t fAdvBlendEqBlacklist;
374     GR_STATIC_ASSERT(kLast_GrBlendEquation < 32);
375 
376     uint32_t fMapBufferFlags;
377     int fBufferMapThreshold;
378 
379     int fMaxRenderTargetSize;
380     int fMaxPreferredRenderTargetSize;
381     int fMaxVertexAttributes;
382     int fMaxTextureSize;
383     int fMaxTileSize;
384     int fMaxRasterSamples;
385     int fMaxWindowRectangles;
386     int fMaxClipAnalyticFPs;
387 
388     GrDriverBugWorkarounds fDriverBugWorkarounds;
389 
390 private:
onApplyOptionsOverrides(const GrContextOptions &)391     virtual void onApplyOptionsOverrides(const GrContextOptions&) {}
onDumpJSON(SkJSONWriter *)392     virtual void onDumpJSON(SkJSONWriter*) const {}
393     virtual bool onSurfaceSupportsWritePixels(const GrSurface*) const = 0;
394     virtual bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
395                                   const SkIRect& srcRect, const SkIPoint& dstPoint) const = 0;
396 
397     // Backends should implement this if they have any extra requirements for use of window
398     // rectangles for a specific GrBackendRenderTarget outside of basic support.
onIsWindowRectanglesSupportedForRT(const GrBackendRenderTarget &)399     virtual bool onIsWindowRectanglesSupportedForRT(const GrBackendRenderTarget&) const {
400         return true;
401     }
402 
403     bool fSuppressPrints : 1;
404     bool fWireframeMode  : 1;
405 
406     typedef SkRefCnt INHERITED;
407 };
408 
409 #endif
410