• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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