Flutter Engine
The Flutter Engine
ycbcrimage.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Google LLC
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 "gm/gm.h"
9
10// This test only works with the Vulkan backend.
11#ifdef SK_VULKAN
12
17#include "include/core/SkSize.h"
22
23#if defined(SK_GRAPHITE)
30
31using VulkanTestContext = skiatest::graphite::VulkanTestContext;
32using SharedContext = skgpu::graphite::SharedContext;
33using VulkanSharedContext = skgpu::graphite::VulkanSharedContext;
34#endif
35
36static void release_ycbcrhelper(void* releaseContext) {
37 VkYcbcrSamplerHelper* ycbcrHelper = reinterpret_cast<VkYcbcrSamplerHelper*>(releaseContext);
38 delete ycbcrHelper;
39}
40
41namespace skiagm {
42
43// This GM exercises the native YCbCr image format on Vulkan
44class YCbCrImageGM : public GM {
45public:
46 YCbCrImageGM() {
47 this->setBGColor(0xFFCCCCCC);
48 }
49
50protected:
51 SkString getName() const override { return SkString("ycbcrimage"); }
52
53 SkISize getISize() override {
55 }
56
57#if defined(SK_GRAPHITE)
58 DrawResult createYCbCrImage(skgpu::graphite::Recorder* recorder,
59 skiatest::graphite::GraphiteTestContext* graphiteTestContext,
60 SkString* errorMsg) {
61 if (!graphiteTestContext || !recorder) {
62 *errorMsg = "Cannot generate a YCbCr image without a valid GraphiteTestContext and "
63 "recorder.";
65 }
66
68
69 VulkanTestContext* vkTestCtxt = static_cast<VulkanTestContext*>(graphiteTestContext);
70
71 const VulkanSharedContext* vulkanSharedCtxt =
72 static_cast<const VulkanSharedContext*>(recorder->priv().sharedContext());
73 SkASSERT(vulkanSharedCtxt);
74
75 std::unique_ptr<VkYcbcrSamplerHelper> ycbcrHelper(
76 new VkYcbcrSamplerHelper(vulkanSharedCtxt,
77 vkTestCtxt->getBackendContext().fPhysicalDevice));
78 if (!ycbcrHelper) {
79 *errorMsg = "Failed to create VkYcbcrSamplerHelper.";
81 }
82 if (!ycbcrHelper->isYCbCrSupported()) {
83 *errorMsg = "YCbCr sampling is not supported.";
85 }
86 if (!ycbcrHelper->createBackendTexture(kImageSize, kImageSize)) {
87 *errorMsg = "Failed to create I420 backend texture.";
89 }
90
91 SkASSERT(!fYCbCrImage);
92
93 // TODO(b/311392779): Once graphite supports YCbCr sampling, actually create the image and
94 // return either DrawResult::Ok or DrawResult::kFail. For now, clean up the helper and
95 // texture manually.
96 recorder->deleteBackendTexture(ycbcrHelper->backendTexture());
97 ycbcrHelper.release();
99 // fYCbCrImage = SkImages::WrapTexture(recorder,
100 // ycbcrHelper->backendTexture(),
101 // kRGB_888x_SkColorType,
102 // kPremul_SkAlphaType,
103 // /*colorSpace=*/nullptr,
104 // release_ycbcrhelper,
105 // ycbcrHelper.get());
106 // SkASSERT(fYCbCrImage);
107 // ycbcrHelper.release();
108 // if (!fYCbCrImage) {
109 // *errorMsg = "Failed to create I420 SkImage.";
110 // return DrawResult::kFail;
111 // }
112 // return DrawResult::kOk;
113 }
114#endif // SK_GRAPHITE
115
116 DrawResult createYCbCrImage(GrDirectContext* dContext, SkString* errorMsg) {
117 std::unique_ptr<VkYcbcrSamplerHelper> ycbcrHelper(new VkYcbcrSamplerHelper(dContext));
118
119 if (!ycbcrHelper->isYCbCrSupported()) {
120 *errorMsg = "YCbCr sampling not supported.";
122 }
123
124 if (!ycbcrHelper->createGrBackendTexture(kImageSize, kImageSize)) {
125 *errorMsg = "Failed to create I420 backend texture.";
127 }
128
129 SkASSERT(!fYCbCrImage);
130 fYCbCrImage = SkImages::BorrowTextureFrom(dContext,
131 ycbcrHelper->grBackendTexture(),
135 nullptr,
136 release_ycbcrhelper,
137 ycbcrHelper.get());
138 ycbcrHelper.release();
139 if (!fYCbCrImage) {
140 *errorMsg = "Failed to create I420 image.";
141 return DrawResult::kFail;
142 }
143
144 return DrawResult::kOk;
145 }
146
147 DrawResult onGpuSetup(SkCanvas* canvas,
148 SkString* errorMsg,
149 GraphiteTestContext* graphiteTestContext) override {
150#if defined(SK_GRAPHITE)
151 skgpu::graphite::Recorder* recorder = canvas->recorder();
152
153 if (recorder) {
154 if (recorder->backend() != skgpu::BackendApi::kVulkan) {
155 *errorMsg = "This GM requires using Vulkan.";
156 return DrawResult::kSkip;
157 }
158
159 return this->createYCbCrImage(recorder, graphiteTestContext, errorMsg);
160 } else
161#endif
162 {
164
165 if (!dContext || dContext->abandoned()) {
166 return DrawResult::kSkip;
167 }
168
169 if (dContext->backend() != GrBackendApi::kVulkan) {
170 *errorMsg = "This GM requires a Vulkan context.";
171 return DrawResult::kSkip;
172 }
173
174 DrawResult result = this->createYCbCrImage(dContext, errorMsg);
175 if (result != DrawResult::kOk) {
176 return result;
177 }
178
179 return DrawResult::kOk;
180 }
181 }
182
183 void onGpuTeardown() override {
184 fYCbCrImage = nullptr;
185 }
186
187 DrawResult onDraw(SkCanvas* canvas, SkString*) override {
188 SkASSERT(fYCbCrImage);
190 return DrawResult::kOk;
191 }
192
193private:
194 static const int kImageSize = 112;
195 static const int kPad = 8;
196
197 sk_sp<SkImage> fYCbCrImage;
198
199 using INHERITED = GpuGM;
200};
201
202//////////////////////////////////////////////////////////////////////////////
203
204DEF_GM(return new YCbCrImageGM;)
205
206} // namespace skiagm
207
208#endif // SK_VULKAN
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT_RELEASE(cond)
Definition: SkAssert.h:100
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kRGB_888x_SkColorType
pixel with 8 bits each for red, green, blue; in 32-bit word
Definition: SkColorType.h:25
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
constexpr int kPad
SK_API GrBackendApi backend() const
bool abandoned() override
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
virtual skgpu::graphite::Recorder * recorder() const
Definition: SkCanvas.cpp:1641
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
BackendApi backend() const
Definition: Recorder.cpp:157
void deleteBackendTexture(const BackendTexture &)
Definition: Recorder.cpp:423
GAsyncResult * result
static const int kImageSize
Definition: flippity.cpp:44
SK_API sk_sp< SkImage > BorrowTextureFrom(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, SkColorType colorType, SkAlphaType alphaType, sk_sp< SkColorSpace > colorSpace, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
DEF_GM(return F(C(clipbox), 0.0f, 0.0f, {})) DEF_GM(return F(C(clipbox)
SkSamplingOptions(SkFilterMode::kLinear))
DrawResult
Definition: gm.h:104
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20