1 /*
2 * Copyright 2019 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 "include/gpu/GrContextThreadSafeProxy.h"
9
10 #include "include/core/SkTextureCompressionType.h"
11 #include "include/private/chromium/GrSurfaceCharacterization.h"
12 #include "src/gpu/ganesh/GrBaseContextPriv.h"
13 #include "src/gpu/ganesh/GrCaps.h"
14 #include "src/gpu/ganesh/GrContextThreadSafeProxyPriv.h"
15 #include "src/gpu/ganesh/GrThreadSafeCache.h"
16 #include "src/gpu/ganesh/GrThreadSafePipelineBuilder.h"
17 #include "src/gpu/ganesh/effects/GrSkSLFP.h"
18 #include "src/gpu/ganesh/surface/SkSurface_Ganesh.h"
19
20 #include <memory>
21
next_id()22 static uint32_t next_id() {
23 static std::atomic<uint32_t> nextID{1};
24 uint32_t id;
25 do {
26 id = nextID.fetch_add(1, std::memory_order_relaxed);
27 } while (id == SK_InvalidGenID);
28 return id;
29 }
30
GrContextThreadSafeProxy(GrBackendApi backend,const GrContextOptions & options)31 GrContextThreadSafeProxy::GrContextThreadSafeProxy(GrBackendApi backend,
32 const GrContextOptions& options)
33 : fBackend(backend), fOptions(options), fContextID(next_id()) {
34 }
35
36 GrContextThreadSafeProxy::~GrContextThreadSafeProxy() = default;
37
init(sk_sp<const GrCaps> caps,sk_sp<GrThreadSafePipelineBuilder> pipelineBuilder)38 void GrContextThreadSafeProxy::init(sk_sp<const GrCaps> caps,
39 sk_sp<GrThreadSafePipelineBuilder> pipelineBuilder) {
40 fCaps = std::move(caps);
41 fTextBlobRedrawCoordinator =
42 std::make_unique<sktext::gpu::TextBlobRedrawCoordinator>(fContextID);
43 fThreadSafeCache = std::make_unique<GrThreadSafeCache>();
44 fPipelineBuilder = std::move(pipelineBuilder);
45 }
46
createCharacterization(size_t cacheMaxResourceBytes,const SkImageInfo & ii,const GrBackendFormat & backendFormat,int sampleCnt,GrSurfaceOrigin origin,const SkSurfaceProps & surfaceProps,skgpu::Mipmapped isMipmapped,bool willUseGLFBO0,bool isTextureable,skgpu::Protected isProtected,bool vkRTSupportsInputAttachment,bool forVulkanSecondaryCommandBuffer)47 GrSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
48 size_t cacheMaxResourceBytes,
49 const SkImageInfo& ii,
50 const GrBackendFormat& backendFormat,
51 int sampleCnt,
52 GrSurfaceOrigin origin,
53 const SkSurfaceProps& surfaceProps,
54 skgpu::Mipmapped isMipmapped,
55 bool willUseGLFBO0,
56 bool isTextureable,
57 skgpu::Protected isProtected,
58 bool vkRTSupportsInputAttachment,
59 bool forVulkanSecondaryCommandBuffer) {
60 SkASSERT(fCaps);
61 if (!backendFormat.isValid()) {
62 return {};
63 }
64
65 SkASSERT(isTextureable || isMipmapped == skgpu::Mipmapped::kNo);
66
67 if (GrBackendApi::kOpenGL != backendFormat.backend() && willUseGLFBO0) {
68 // The willUseGLFBO0 flags can only be used for a GL backend.
69 return {};
70 }
71
72 if (GrBackendApi::kVulkan != backendFormat.backend() &&
73 (vkRTSupportsInputAttachment || forVulkanSecondaryCommandBuffer)) {
74 // The vkRTSupportsInputAttachment and forVulkanSecondaryCommandBuffer flags can only be
75 // used for a Vulkan backend.
76 return {};
77 }
78
79 if (!fCaps->mipmapSupport()) {
80 isMipmapped = skgpu::Mipmapped::kNo;
81 }
82
83 if (ii.width() < 1 || ii.width() > fCaps->maxRenderTargetSize() ||
84 ii.height() < 1 || ii.height() > fCaps->maxRenderTargetSize()) {
85 return {};
86 }
87
88 GrColorType grColorType = SkColorTypeToGrColorType(ii.colorType());
89
90 if (!fCaps->areColorTypeAndFormatCompatible(grColorType, backendFormat)) {
91 return {};
92 }
93
94 if (!fCaps->isFormatAsColorTypeRenderable(grColorType, backendFormat, sampleCnt)) {
95 return {};
96 }
97
98 sampleCnt = fCaps->getRenderTargetSampleCount(sampleCnt, backendFormat);
99 SkASSERT(sampleCnt);
100
101 if (willUseGLFBO0 && isTextureable) {
102 return {};
103 }
104
105 if (isTextureable && !fCaps->isFormatTexturable(backendFormat, backendFormat.textureType())) {
106 // Skia doesn't agree that this is textureable.
107 return {};
108 }
109
110 if (GrBackendApi::kVulkan == backendFormat.backend()) {
111 if (!isValidCharacterizationForVulkan(fCaps,
112 isTextureable,
113 isMipmapped,
114 isProtected,
115 vkRTSupportsInputAttachment,
116 forVulkanSecondaryCommandBuffer)) {
117 return {};
118 }
119 }
120
121 return GrSurfaceCharacterization(
122 sk_ref_sp<GrContextThreadSafeProxy>(this),
123 cacheMaxResourceBytes,
124 ii,
125 backendFormat,
126 origin,
127 sampleCnt,
128 GrSurfaceCharacterization::Textureable(isTextureable),
129 isMipmapped,
130 GrSurfaceCharacterization::UsesGLFBO0(willUseGLFBO0),
131 GrSurfaceCharacterization::VkRTSupportsInputAttachment(vkRTSupportsInputAttachment),
132 GrSurfaceCharacterization::VulkanSecondaryCBCompatible(forVulkanSecondaryCommandBuffer),
133 isProtected,
134 surfaceProps);
135 }
136
isValidCharacterizationForVulkan(sk_sp<const GrCaps>,bool isTextureable,skgpu::Mipmapped isMipmapped,skgpu::Protected isProtected,bool vkRTSupportsInputAttachment,bool forVulkanSecondaryCommandBuffer)137 bool GrContextThreadSafeProxy::isValidCharacterizationForVulkan(
138 sk_sp<const GrCaps>,
139 bool isTextureable,
140 skgpu::Mipmapped isMipmapped,
141 skgpu::Protected isProtected,
142 bool vkRTSupportsInputAttachment,
143 bool forVulkanSecondaryCommandBuffer) {
144 return false; // handled by a subclass
145 }
146
defaultBackendFormat(SkColorType skColorType,GrRenderable renderable) const147 GrBackendFormat GrContextThreadSafeProxy::defaultBackendFormat(SkColorType skColorType,
148 GrRenderable renderable) const {
149 SkASSERT(fCaps);
150 GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
151
152 GrBackendFormat format = fCaps->getDefaultBackendFormat(grColorType, renderable);
153 if (!format.isValid()) {
154 return GrBackendFormat();
155 }
156
157 SkASSERT(renderable == GrRenderable::kNo ||
158 fCaps->isFormatAsColorTypeRenderable(grColorType, format));
159
160 return format;
161 }
162
compressedBackendFormat(SkTextureCompressionType c) const163 GrBackendFormat GrContextThreadSafeProxy::compressedBackendFormat(SkTextureCompressionType c) const {
164 SkASSERT(fCaps);
165
166 GrBackendFormat format = fCaps->getBackendFormatFromCompressionType(c);
167
168 SkASSERT(!format.isValid() || fCaps->isFormatTexturable(format, GrTextureType::k2D));
169 return format;
170 }
171
maxSurfaceSampleCountForColorType(SkColorType colorType) const172 int GrContextThreadSafeProxy::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
173 SkASSERT(fCaps);
174
175 GrBackendFormat format = fCaps->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
176 GrRenderable::kYes);
177 return fCaps->maxRenderTargetSampleCount(format);
178 }
179
abandonContext()180 void GrContextThreadSafeProxy::abandonContext() {
181 if (!fAbandoned.exchange(true)) {
182 fTextBlobRedrawCoordinator->freeAll();
183 }
184 }
185
abandoned() const186 bool GrContextThreadSafeProxy::abandoned() const {
187 return fAbandoned;
188 }
189
190 ////////////////////////////////////////////////////////////////////////////////
Make(GrBackendApi backend,const GrContextOptions & options)191 sk_sp<GrContextThreadSafeProxy> GrContextThreadSafeProxyPriv::Make(
192 GrBackendApi backend,
193 const GrContextOptions& options) {
194 return sk_sp<GrContextThreadSafeProxy>(new GrContextThreadSafeProxy(backend, options));
195 }
196
init(sk_sp<const GrCaps> caps,sk_sp<GrThreadSafePipelineBuilder> builder) const197 void GrContextThreadSafeProxyPriv::init(sk_sp<const GrCaps> caps,
198 sk_sp<GrThreadSafePipelineBuilder> builder) const {
199 fProxy->init(std::move(caps), std::move(builder));
200 }
201