• 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 "src/gpu/vk/GrVkSecondaryCBDrawContext.h"
9 
10 #include "include/core/SkDeferredDisplayList.h"
11 #include "include/core/SkImageInfo.h"
12 #include "include/core/SkSurfaceCharacterization.h"
13 #include "include/gpu/GrDirectContext.h"
14 #include "include/gpu/GrRecordingContext.h"
15 #include "include/gpu/vk/GrVkTypes.h"
16 #include "src/core/SkSurfacePriv.h"
17 #include "src/gpu/GrContextThreadSafeProxyPriv.h"
18 #include "src/gpu/GrDirectContextPriv.h"
19 #include "src/gpu/GrProxyProvider.h"
20 #include "src/gpu/GrRecordingContextPriv.h"
21 #include "src/gpu/GrRenderTargetProxy.h"
22 #include "src/gpu/GrSurfaceProxyView.h"
23 
Make(GrRecordingContext * rContext,const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo,const SkSurfaceProps * props)24 sk_sp<GrVkSecondaryCBDrawContext> GrVkSecondaryCBDrawContext::Make(GrRecordingContext* rContext,
25                                                                    const SkImageInfo& imageInfo,
26                                                                    const GrVkDrawableInfo& vkInfo,
27                                                                    const SkSurfaceProps* props) {
28     if (!rContext) {
29         return nullptr;
30     }
31 
32     if (rContext->backend() != GrBackendApi::kVulkan) {
33         return nullptr;
34     }
35 
36     sk_sp<GrSurfaceProxy> proxy(
37             rContext->priv().proxyProvider()->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
38                                                                                   vkInfo));
39     if (!proxy) {
40         return nullptr;
41     }
42 
43     SkASSERT(proxy->isInstantiated());
44 
45     auto device = rContext->priv().createDevice(SkColorTypeToGrColorType(imageInfo.colorType()),
46                                                 std::move(proxy),
47                                                 imageInfo.refColorSpace(),
48                                                 kTopLeft_GrSurfaceOrigin,
49                                                 SkSurfacePropsCopyOrDefault(props),
50                                                 skgpu::BaseDevice::InitContents::kUninit);
51     if (!device) {
52         return nullptr;
53     }
54 
55     return sk_sp<GrVkSecondaryCBDrawContext>(new GrVkSecondaryCBDrawContext(std::move(device),
56                                                                             props));
57 }
58 
GrVkSecondaryCBDrawContext(sk_sp<skgpu::BaseDevice> device,const SkSurfaceProps * props)59 GrVkSecondaryCBDrawContext::GrVkSecondaryCBDrawContext(sk_sp<skgpu::BaseDevice> device,
60                                                        const SkSurfaceProps* props)
61     : fDevice(device)
62     , fProps(SkSurfacePropsCopyOrDefault(props)) {}
63 
~GrVkSecondaryCBDrawContext()64 GrVkSecondaryCBDrawContext::~GrVkSecondaryCBDrawContext() {
65     SkASSERT(!fDevice);
66     SkASSERT(!fCachedCanvas.get());
67 }
68 
getCanvas()69 SkCanvas* GrVkSecondaryCBDrawContext::getCanvas() {
70     if (!fCachedCanvas) {
71         fCachedCanvas = std::make_unique<SkCanvas>(fDevice);
72     }
73     return fCachedCanvas.get();
74 }
75 
flush()76 void GrVkSecondaryCBDrawContext::flush() {
77     auto dContext = GrAsDirectContext(fDevice->recordingContext());
78 
79     if (dContext) {
80         dContext->priv().flushSurface(fDevice->targetProxy());
81         dContext->submit();
82     }
83 }
84 
wait(int numSemaphores,const GrBackendSemaphore waitSemaphores[],bool deleteSemaphoresAfterWait)85 bool GrVkSecondaryCBDrawContext::wait(int numSemaphores,
86                                       const GrBackendSemaphore waitSemaphores[],
87                                       bool deleteSemaphoresAfterWait) {
88     return fDevice->wait(numSemaphores, waitSemaphores, deleteSemaphoresAfterWait);
89 }
90 
releaseResources()91 void GrVkSecondaryCBDrawContext::releaseResources() {
92     fCachedCanvas.reset();
93     fDevice.reset();
94 }
95 
characterize(SkSurfaceCharacterization * characterization) const96 bool GrVkSecondaryCBDrawContext::characterize(SkSurfaceCharacterization* characterization) const {
97     auto direct = fDevice->recordingContext()->asDirectContext();
98     if (!direct) {
99         return false;
100     }
101 
102     SkImageInfo ii = fDevice->imageInfo();
103     if (ii.colorType() == kUnknown_SkColorType) {
104         return false;
105     }
106 
107     GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
108     size_t maxResourceBytes = direct->getResourceCacheLimit();
109 
110     // We current don't support textured GrVkSecondaryCBDrawContexts.
111     SkASSERT(!readSurfaceView.asTextureProxy());
112 
113     GrBackendFormat format = readSurfaceView.asRenderTargetProxy()->backendFormat();
114     int numSamples = readSurfaceView.asRenderTargetProxy()->numSamples();
115     GrProtected isProtected = readSurfaceView.asRenderTargetProxy()->isProtected();
116 
117     characterization->set(direct->threadSafeProxy(),
118                           maxResourceBytes,
119                           ii,
120                           format,
121                           readSurfaceView.origin(),
122                           numSamples,
123                           SkSurfaceCharacterization::Textureable(false),
124                           SkSurfaceCharacterization::MipMapped(false),
125                           SkSurfaceCharacterization::UsesGLFBO0(false),
126                           SkSurfaceCharacterization::VkRTSupportsInputAttachment(false),
127                           SkSurfaceCharacterization::VulkanSecondaryCBCompatible(true),
128                           isProtected,
129                           this->props());
130 
131     return true;
132 }
133 
isCompatible(const SkSurfaceCharacterization & characterization) const134 bool GrVkSecondaryCBDrawContext::isCompatible(
135         const SkSurfaceCharacterization& characterization) const {
136 
137     auto dContext = fDevice->recordingContext()->asDirectContext();
138     if (!dContext) {
139         return false;
140     }
141 
142     if (!characterization.isValid()) {
143         return false;
144     }
145 
146     if (!characterization.vulkanSecondaryCBCompatible()) {
147         return false;
148     }
149 
150     if (characterization.isTextureable()) {
151         // We don't support textureable DDL when rendering to a GrVkSecondaryCBDrawContext.
152         return false;
153     }
154 
155     if (characterization.usesGLFBO0()) {
156         return false;
157     }
158 
159     SkImageInfo ii = fDevice->imageInfo();
160     if (ii.colorType() == kUnknown_SkColorType) {
161         return false;
162     }
163 
164     GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
165     // As long as the current state in the context allows for greater or equal resources,
166     // we allow the DDL to be replayed.
167     // DDL TODO: should we just remove the resource check and ignore the cache limits on playback?
168     size_t maxResourceBytes = dContext->getResourceCacheLimit();
169 
170     GrBackendFormat format = readSurfaceView.asRenderTargetProxy()->backendFormat();
171     int numSamples = readSurfaceView.asRenderTargetProxy()->numSamples();
172     GrProtected isProtected = readSurfaceView.asRenderTargetProxy()->isProtected();
173 
174     return characterization.contextInfo() &&
175            characterization.contextInfo()->priv().matches(dContext) &&
176            characterization.cacheMaxResourceBytes() <= maxResourceBytes &&
177            characterization.origin() == readSurfaceView.origin() &&
178            characterization.backendFormat() == format &&
179            characterization.width() == ii.width() &&
180            characterization.height() == ii.height() &&
181            characterization.colorType() == ii.colorType() &&
182            characterization.sampleCount() == numSamples &&
183            SkColorSpace::Equals(characterization.colorSpace(), ii.colorInfo().colorSpace()) &&
184            characterization.isProtected() == isProtected &&
185            characterization.surfaceProps() == fDevice->surfaceProps();
186 }
187 
188 #ifndef SK_DDL_IS_UNIQUE_POINTER
draw(sk_sp<const SkDeferredDisplayList> ddl)189 bool GrVkSecondaryCBDrawContext::draw(sk_sp<const SkDeferredDisplayList> ddl) {
190 #else
191 bool GrVkSecondaryCBDrawContext::draw(const SkDeferredDisplayList* ddl) {
192 #endif
193     if (!ddl || !this->isCompatible(ddl->characterization())) {
194         return false;
195     }
196 
197     auto direct = fDevice->recordingContext()->asDirectContext();
198     if (!direct) {
199         return false;
200     }
201 
202     GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
203 
204     direct->priv().createDDLTask(std::move(ddl), readSurfaceView.asRenderTargetProxyRef(), {0, 0});
205     return true;
206 }
207