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