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 "vk/GrVkSecondaryCBDrawContext.h"
9
10 #include "GrContext.h"
11 #include "GrContextPriv.h"
12 #include "GrContextThreadSafeProxyPriv.h"
13 #include "GrRenderTargetContext.h"
14 #include "SkDeferredDisplayList.h"
15 #include "SkGpuDevice.h"
16 #include "SkImageInfo.h"
17 #include "SkSurfaceCharacterization.h"
18 #include "SkSurfacePriv.h"
19 #include "vk/GrVkTypes.h"
20
Make(GrContext * ctx,const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo,const SkSurfaceProps * props)21 sk_sp<GrVkSecondaryCBDrawContext> GrVkSecondaryCBDrawContext::Make(GrContext* ctx,
22 const SkImageInfo& imageInfo,
23 const GrVkDrawableInfo& vkInfo,
24 const SkSurfaceProps* props) {
25 if (!ctx) {
26 return nullptr;
27 }
28
29 if (ctx->backend() != GrBackendApi::kVulkan) {
30 return nullptr;
31 }
32
33 sk_sp<GrRenderTargetContext> rtc(
34 ctx->priv().makeVulkanSecondaryCBRenderTargetContext(imageInfo, vkInfo, props));
35
36 int width = rtc->width();
37 int height = rtc->height();
38
39 sk_sp<SkGpuDevice> device(SkGpuDevice::Make(ctx, std::move(rtc), width, height,
40 SkGpuDevice::kUninit_InitContents));
41 if (!device) {
42 return nullptr;
43 }
44
45 return sk_sp<GrVkSecondaryCBDrawContext>(new GrVkSecondaryCBDrawContext(std::move(device),
46 props));
47 }
48
GrVkSecondaryCBDrawContext(sk_sp<SkGpuDevice> device,const SkSurfaceProps * props)49 GrVkSecondaryCBDrawContext::GrVkSecondaryCBDrawContext(sk_sp<SkGpuDevice> device,
50 const SkSurfaceProps* props)
51 : fDevice(device)
52 , fProps(SkSurfacePropsCopyOrDefault(props)) {}
53
~GrVkSecondaryCBDrawContext()54 GrVkSecondaryCBDrawContext::~GrVkSecondaryCBDrawContext() {
55 SkASSERT(!fDevice);
56 SkASSERT(!fCachedCanvas.get());
57 }
58
getCanvas()59 SkCanvas* GrVkSecondaryCBDrawContext::getCanvas() {
60 if (!fCachedCanvas) {
61 fCachedCanvas = std::unique_ptr<SkCanvas>(new SkCanvas(fDevice));
62 }
63 return fCachedCanvas.get();
64 }
65
flush()66 void GrVkSecondaryCBDrawContext::flush() {
67 fDevice->flush();
68 }
69
wait(int numSemaphores,const GrBackendSemaphore waitSemaphores[])70 bool GrVkSecondaryCBDrawContext::wait(int numSemaphores,
71 const GrBackendSemaphore waitSemaphores[]) {
72 return fDevice->wait(numSemaphores, waitSemaphores);
73 }
74
releaseResources()75 void GrVkSecondaryCBDrawContext::releaseResources() {
76 fCachedCanvas.reset();
77 fDevice.reset();
78 }
79
characterize(SkSurfaceCharacterization * characterization) const80 bool GrVkSecondaryCBDrawContext::characterize(SkSurfaceCharacterization* characterization) const {
81 GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
82 GrContext* ctx = fDevice->context();
83
84 int maxResourceCount;
85 size_t maxResourceBytes;
86 ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
87
88 // We current don't support textured GrVkSecondaryCBDrawContexts.
89 SkASSERT(!rtc->asTextureProxy());
90
91 // TODO: the addition of colorType to the surfaceContext should remove this calculation
92 SkColorType ct;
93 if (!GrPixelConfigToColorType(rtc->colorSpaceInfo().config(), &ct)) {
94 return false;
95 }
96
97 SkImageInfo ii = SkImageInfo::Make(rtc->width(), rtc->height(), ct, kPremul_SkAlphaType,
98 rtc->colorSpaceInfo().refColorSpace());
99
100 characterization->set(ctx->threadSafeProxy(), maxResourceBytes, ii, rtc->origin(),
101 rtc->colorSpaceInfo().config(), rtc->fsaaType(), rtc->numStencilSamples(),
102 SkSurfaceCharacterization::Textureable(false),
103 SkSurfaceCharacterization::MipMapped(false),
104 SkSurfaceCharacterization::UsesGLFBO0(false),
105 SkSurfaceCharacterization::VulkanSecondaryCBCompatible(true),
106 this->props());
107
108 return true;
109 }
110
isCompatible(const SkSurfaceCharacterization & characterization) const111 bool GrVkSecondaryCBDrawContext::isCompatible(
112 const SkSurfaceCharacterization& characterization) const {
113 GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
114 GrContext* ctx = fDevice->context();
115
116 if (!characterization.isValid()) {
117 return false;
118 }
119
120 if (!characterization.vulkanSecondaryCBCompatible()) {
121 return false;
122 }
123
124 // As long as the current state in the context allows for greater or equal resources,
125 // we allow the DDL to be replayed.
126 // DDL TODO: should we just remove the resource check and ignore the cache limits on playback?
127 int maxResourceCount;
128 size_t maxResourceBytes;
129 ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
130
131 if (characterization.isTextureable()) {
132 // We don't support textureable DDL when rendering to a GrVkSecondaryCBDrawContext.
133 return false;
134 }
135
136 if (characterization.usesGLFBO0()) {
137 return false;
138 }
139
140 // TODO: the addition of colorType to the surfaceContext should remove this calculation
141 SkColorType rtcColorType;
142 if (!GrPixelConfigToColorType(rtc->colorSpaceInfo().config(), &rtcColorType)) {
143 return false;
144 }
145
146 return characterization.contextInfo() && characterization.contextInfo()->priv().matches(ctx) &&
147 characterization.cacheMaxResourceBytes() <= maxResourceBytes &&
148 characterization.origin() == rtc->origin() &&
149 characterization.config() == rtc->colorSpaceInfo().config() &&
150 characterization.width() == rtc->width() &&
151 characterization.height() == rtc->height() &&
152 characterization.colorType() == rtcColorType &&
153 characterization.fsaaType() == rtc->fsaaType() &&
154 characterization.stencilCount() == rtc->numStencilSamples() &&
155 SkColorSpace::Equals(characterization.colorSpace(),
156 rtc->colorSpaceInfo().colorSpace()) &&
157 characterization.surfaceProps() == rtc->surfaceProps();
158 }
159
draw(SkDeferredDisplayList * ddl)160 bool GrVkSecondaryCBDrawContext::draw(SkDeferredDisplayList* ddl) {
161 if (!ddl || !this->isCompatible(ddl->characterization())) {
162 return false;
163 }
164
165 GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
166 GrContext* ctx = fDevice->context();
167
168 ctx->priv().copyOpListsFromDDL(ddl, rtc->asRenderTargetProxy());
169 return true;
170 }
171
172
173