blob: aa02cabf87809d6462d43ab424d113d5f54d74e5 [file] [log] [blame]
Michael Ludwigd9958f82019-03-21 13:08:36 -04001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "tools/gpu/YUVUtils.h"
Michael Ludwigd9958f82019-03-21 13:08:36 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkData.h"
Brian Salomonefb5f072020-07-28 21:06:43 -040011#include "include/gpu/GrRecordingContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/codec/SkCodecImageGenerator.h"
Brian Salomon87d42e52020-08-24 09:18:16 -040013#include "src/core/SkYUVAInfoPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/GrContextPriv.h"
Brian Salomonefb5f072020-07-28 21:06:43 -040015#include "src/gpu/GrRecordingContextPriv.h"
Michael Ludwigd9958f82019-03-21 13:08:36 -040016
17namespace sk_gpu_test {
18
Brian Salomon87d42e52020-08-24 09:18:16 -040019YUVAPixmaps::YUVAPixmaps(const SkYUVAInfo& yuvaInfo,
20 SkColorType colorTypes[SkYUVAInfo::kMaxPlanes],
21 size_t rowBytes[SkYUVAInfo::kMaxPlanes])
22 : fYUVAInfo(yuvaInfo) {
23 if (yuvaInfo.dimensions().isEmpty()) {
24 return;
25 }
26 SkISize planeDims[SkYUVAInfo::kMaxPlanes];
27 SkImageInfo ii[SkYUVAInfo::kMaxPlanes];
28 size_t planeSizes[SkYUVAInfo::kMaxPlanes];
29 size_t totalBytes = yuvaInfo.computeTotalBytes(rowBytes, planeSizes);
30 int numPlanes = yuvaInfo.expectedPlaneDims(planeDims);
31 for (int i = 0; i < numPlanes; ++i) {
32 ii[i] = SkImageInfo::Make(planeDims[i], colorTypes[i], kPremul_SkAlphaType);
33 if (!ii[i].validRowBytes(rowBytes[i])) {
34 return;
35 }
36 }
37
38 fStorage.reset(new char[totalBytes]);
39 char* addr = fStorage.get();
40 for (int i = 0; i < numPlanes; ++i) {
41 fPlanes[i].reset(ii[i], addr, rowBytes[i]);
42 addr += planeSizes[i];
43 }
44 fIsValid = true;
45}
46
47bool YUVAPixmaps::toLegacy(SkYUVASizeInfo* yuvaSizeInfo, SkYUVAIndex yuvaIndices[4]) {
48 if (!this->isValid()) {
49 return false;
50 }
51 return SkYUVAInfoPriv::InitLegacyInfo(fYUVAInfo, fPlanes, yuvaSizeInfo, yuvaIndices);
52}
53
Brian Salomon6db78b82020-07-31 08:57:48 -040054std::unique_ptr<LazyYUVImage> LazyYUVImage::Make(sk_sp<SkData> data, GrMipmapped mipmapped) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040055 std::unique_ptr<LazyYUVImage> image(new LazyYUVImage());
Brian Salomon6db78b82020-07-31 08:57:48 -040056 if (image->reset(std::move(data), mipmapped)) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040057 return image;
58 } else {
59 return nullptr;
60 }
61}
62
Brian Salomonefb5f072020-07-28 21:06:43 -040063sk_sp<SkImage> LazyYUVImage::refImage(GrRecordingContext* rContext) {
64 if (this->ensureYUVImage(rContext)) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040065 return fYUVImage;
66 } else {
67 return nullptr;
68 }
69}
70
Brian Salomonefb5f072020-07-28 21:06:43 -040071const SkImage* LazyYUVImage::getImage(GrRecordingContext* rContext) {
72 if (this->ensureYUVImage(rContext)) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040073 return fYUVImage.get();
74 } else {
75 return nullptr;
76 }
77}
78
Brian Salomon6db78b82020-07-31 08:57:48 -040079bool LazyYUVImage::reset(sk_sp<SkData> data, GrMipmapped mipmapped) {
80 fMipmapped = mipmapped;
Michael Ludwigd9958f82019-03-21 13:08:36 -040081 auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(data);
82 if (!codec) {
83 return false;
84 }
85
Brian Salomon87d42e52020-08-24 09:18:16 -040086 SkColorType colorTypes[4];
87 size_t rowBytes[4];
88 SkYUVAInfo yuvaInfo;
89 if (!codec->queryYUVAInfo(&yuvaInfo, colorTypes, rowBytes)) {
90 return false;
91 }
92 fPixmaps = YUVAPixmaps(yuvaInfo, colorTypes, rowBytes);
93 if (!fPixmaps.isValid()) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040094 return false;
95 }
96
Brian Salomon87d42e52020-08-24 09:18:16 -040097 if (!codec->getYUVAPlanes(fPixmaps.planes())) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040098 return false;
99 }
100
Brian Salomon87d42e52020-08-24 09:18:16 -0400101 if (!fPixmaps.toLegacy(&fSizeInfo, fComponents)) {
102 return false;
Michael Ludwigd9958f82019-03-21 13:08:36 -0400103 }
104 // The SkPixmap data is fully configured now for MakeFromYUVAPixmaps once we get a GrContext
105 return true;
106}
107
Brian Salomonefb5f072020-07-28 21:06:43 -0400108bool LazyYUVImage::ensureYUVImage(GrRecordingContext* rContext) {
109 if (!rContext) {
Michael Ludwigd9958f82019-03-21 13:08:36 -0400110 return false; // Cannot make a YUV image from planes
111 }
Brian Salomonefb5f072020-07-28 21:06:43 -0400112 if (fYUVImage && fYUVImage->isValid(rContext)) {
113 return true; // Have already made a YUV image valid for this context.
Michael Ludwigd9958f82019-03-21 13:08:36 -0400114 }
Brian Salomonefb5f072020-07-28 21:06:43 -0400115 // Try to make a new YUV image for this context.
116 fYUVImage = SkImage::MakeFromYUVAPixmaps(rContext->priv().backdoor(),
Brian Salomon87d42e52020-08-24 09:18:16 -0400117 fPixmaps.yuvaInfo().yuvColorSpace(),
118 fPixmaps.planes(),
Brian Salomonefb5f072020-07-28 21:06:43 -0400119 fComponents,
120 fSizeInfo.fSizes[0],
121 kTopLeft_GrSurfaceOrigin,
Brian Salomon6db78b82020-07-31 08:57:48 -0400122 static_cast<bool>(fMipmapped),
Brian Salomonefb5f072020-07-28 21:06:43 -0400123 false);
Michael Ludwigd9958f82019-03-21 13:08:36 -0400124 return fYUVImage != nullptr;
125}
126
Robert Phillipsf105d382020-06-19 14:27:14 -0400127///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips057c33f2020-07-17 11:59:01 -0400128void YUVABackendReleaseContext::Unwind(GrDirectContext* dContext,
129 YUVABackendReleaseContext* beContext,
Robert Phillips98c39ba2020-06-26 10:01:19 -0400130 bool fullFlush) {
131
Robert Phillipsf105d382020-06-19 14:27:14 -0400132 // Some backends (e.g., Vulkan) require that all work associated w/ texture
133 // creation be completed before deleting the textures.
Robert Phillips98c39ba2020-06-26 10:01:19 -0400134 if (fullFlush) {
135 // If the release context client performed some operations other than backend texture
136 // creation then we may require a full flush to ensure that all the work is completed.
Robert Phillips057c33f2020-07-17 11:59:01 -0400137 dContext->flush();
138 dContext->submit(true);
Robert Phillips98c39ba2020-06-26 10:01:19 -0400139 } else {
Robert Phillips057c33f2020-07-17 11:59:01 -0400140 dContext->submit();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400141
142 while (!beContext->creationCompleted()) {
Robert Phillips057c33f2020-07-17 11:59:01 -0400143 dContext->checkAsyncWorkCompletion();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400144 }
145 }
Robert Phillipsf105d382020-06-19 14:27:14 -0400146
147 delete beContext;
148}
149
Robert Phillips057c33f2020-07-17 11:59:01 -0400150YUVABackendReleaseContext::YUVABackendReleaseContext(GrDirectContext* dContext)
151 : fDContext(dContext) {
Robert Phillipsf105d382020-06-19 14:27:14 -0400152}
153
154YUVABackendReleaseContext::~YUVABackendReleaseContext() {
155 for (int i = 0; i < 4; ++i) {
156 if (fBETextures[i].isValid()) {
Robert Phillips98c39ba2020-06-26 10:01:19 -0400157 SkASSERT(fCreationComplete[i]);
Robert Phillips057c33f2020-07-17 11:59:01 -0400158 fDContext->deleteBackendTexture(fBETextures[i]);
Robert Phillipsf105d382020-06-19 14:27:14 -0400159 }
160 }
161}
162
Robert Phillips98c39ba2020-06-26 10:01:19 -0400163template<int I> static void CreationComplete(void* releaseContext) {
164 auto beContext = reinterpret_cast<YUVABackendReleaseContext*>(releaseContext);
165 beContext->setCreationComplete(I);
166}
167
168GrGpuFinishedProc YUVABackendReleaseContext::CreationCompleteProc(int index) {
169 SkASSERT(index >= 0 && index < 4);
170
171 switch (index) {
172 case 0: return CreationComplete<0>;
173 case 1: return CreationComplete<1>;
174 case 2: return CreationComplete<2>;
175 case 3: return CreationComplete<3>;
176 }
177
178 SK_ABORT("Invalid YUVA Index.");
179 return nullptr;
180}
181
Michael Ludwigd9958f82019-03-21 13:08:36 -0400182} // namespace sk_gpu_test