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