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