xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrContextThreadSafeProxy.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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