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/GrContextThreadSafeProxyPriv.h" |
12 | |
13 | #include "include/core/SkSurfaceCharacterization.h" |
14 | #include "src/gpu/GrBaseContextPriv.h" |
15 | #include "src/gpu/GrCaps.h" |
16 | #include "src/gpu/effects/GrSkSLFP.h" |
17 | #include "src/image/SkSurface_Gpu.h" |
18 | |
19 | #ifdef SK_VULKAN |
20 | #include "src/gpu/vk/GrVkCaps.h" |
21 | #endif |
22 | |
23 | static int32_t next_id() { |
24 | static std::atomic<int32_t> nextID{1}; |
25 | int32_t id; |
26 | do { |
27 | id = nextID++; |
28 | } while (id == SK_InvalidGenID); |
29 | return id; |
30 | } |
31 | |
32 | GrContextThreadSafeProxy::GrContextThreadSafeProxy(GrBackendApi backend, |
33 | const GrContextOptions& options) |
34 | : fBackend(backend), fOptions(options), fContextID(next_id()) { |
35 | } |
36 | |
37 | GrContextThreadSafeProxy::~GrContextThreadSafeProxy() = default; |
38 | |
39 | void GrContextThreadSafeProxy::init(sk_sp<const GrCaps> caps) { |
40 | fCaps = std::move(caps); |
41 | fTextBlobCache = std::make_unique<GrTextBlobCache>(fContextID); |
42 | } |
43 | |
44 | SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization( |
45 | size_t cacheMaxResourceBytes, |
46 | const SkImageInfo& ii, const GrBackendFormat& backendFormat, |
47 | int sampleCnt, GrSurfaceOrigin origin, |
48 | const SkSurfaceProps& surfaceProps, |
49 | bool isMipMapped, bool willUseGLFBO0, bool isTextureable, |
50 | GrProtected isProtected) { |
51 | SkASSERT(fCaps); |
52 | if (!backendFormat.isValid()) { |
53 | return {}; |
54 | } |
55 | |
56 | SkASSERT(isTextureable || !isMipMapped); |
57 | |
58 | if (GrBackendApi::kOpenGL != backendFormat.backend() && willUseGLFBO0) { |
59 | // The willUseGLFBO0 flags can only be used for a GL backend. |
60 | return {}; |
61 | } |
62 | |
63 | if (!fCaps->mipmapSupport()) { |
64 | isMipMapped = false; |
65 | } |
66 | |
67 | if (ii.width() < 1 || ii.width() > fCaps->maxRenderTargetSize() || |
68 | ii.height() < 1 || ii.height() > fCaps->maxRenderTargetSize()) { |
69 | return {}; |
70 | } |
71 | |
72 | GrColorType grColorType = SkColorTypeToGrColorType(ii.colorType()); |
73 | |
74 | if (!fCaps->areColorTypeAndFormatCompatible(grColorType, backendFormat)) { |
75 | return {}; |
76 | } |
77 | |
78 | if (!fCaps->isFormatAsColorTypeRenderable(grColorType, backendFormat, sampleCnt)) { |
79 | return {}; |
80 | } |
81 | |
82 | sampleCnt = fCaps->getRenderTargetSampleCount(sampleCnt, backendFormat); |
83 | SkASSERT(sampleCnt); |
84 | |
85 | if (willUseGLFBO0 && isTextureable) { |
86 | return {}; |
87 | } |
88 | |
89 | if (isTextureable && !fCaps->isFormatTexturable(backendFormat)) { |
90 | // Skia doesn't agree that this is textureable. |
91 | return {}; |
92 | } |
93 | |
94 | if (GrBackendApi::kVulkan == backendFormat.backend()) { |
95 | if (GrBackendApi::kVulkan != fBackend) { |
96 | return {}; |
97 | } |
98 | |
99 | #ifdef SK_VULKAN |
100 | const GrVkCaps* vkCaps = (const GrVkCaps*) fCaps.get(); |
101 | |
102 | // The protection status of the characterization and the context need to match |
103 | if (isProtected != GrProtected(vkCaps->supportsProtectedMemory())) { |
104 | return {}; |
105 | } |
106 | #endif |
107 | } |
108 | |
109 | return SkSurfaceCharacterization(sk_ref_sp<GrContextThreadSafeProxy>(this), |
110 | cacheMaxResourceBytes, ii, backendFormat, |
111 | origin, sampleCnt, |
112 | SkSurfaceCharacterization::Textureable(isTextureable), |
113 | SkSurfaceCharacterization::MipMapped(isMipMapped), |
114 | SkSurfaceCharacterization::UsesGLFBO0(willUseGLFBO0), |
115 | SkSurfaceCharacterization::VulkanSecondaryCBCompatible(false), |
116 | isProtected, |
117 | surfaceProps); |
118 | } |
119 | |
120 | GrBackendFormat GrContextThreadSafeProxy::defaultBackendFormat(SkColorType skColorType, |
121 | GrRenderable renderable) const { |
122 | SkASSERT(fCaps); |
123 | GrColorType grColorType = SkColorTypeToGrColorType(skColorType); |
124 | |
125 | GrBackendFormat format = fCaps->getDefaultBackendFormat(grColorType, renderable); |
126 | if (!format.isValid()) { |
127 | return GrBackendFormat(); |
128 | } |
129 | |
130 | SkASSERT(renderable == GrRenderable::kNo || |
131 | fCaps->isFormatAsColorTypeRenderable(grColorType, format)); |
132 | |
133 | return format; |
134 | } |
135 | |
136 | void GrContextThreadSafeProxy::abandonContext() { |
137 | if (!fAbandoned.exchange(true)) { |
138 | fTextBlobCache->freeAll(); |
139 | } |
140 | } |
141 | |
142 | bool GrContextThreadSafeProxy::abandoned() const { |
143 | return fAbandoned; |
144 | } |
145 | |
146 | //////////////////////////////////////////////////////////////////////////////// |
147 | sk_sp<GrContextThreadSafeProxy> GrContextThreadSafeProxyPriv::Make( |
148 | GrBackendApi backend, |
149 | const GrContextOptions& options) { |
150 | return sk_sp<GrContextThreadSafeProxy>(new GrContextThreadSafeProxy(backend, options)); |
151 | } |
152 | |
153 | |