• 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 <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