blob: 7b842509aca355ea8a5101d4662ec59059f1801f [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"
13#include "src/gpu/GrContextPriv.h"
Brian Salomonefb5f072020-07-28 21:06:43 -040014#include "src/gpu/GrRecordingContextPriv.h"
Michael Ludwigd9958f82019-03-21 13:08:36 -040015
16namespace sk_gpu_test {
17
18std::unique_ptr<LazyYUVImage> LazyYUVImage::Make(sk_sp<SkData> data) {
19 std::unique_ptr<LazyYUVImage> image(new LazyYUVImage());
20 if (image->reset(std::move(data))) {
21 return image;
22 } else {
23 return nullptr;
24 }
25}
26
Brian Salomonefb5f072020-07-28 21:06:43 -040027sk_sp<SkImage> LazyYUVImage::refImage(GrRecordingContext* rContext) {
28 if (this->ensureYUVImage(rContext)) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040029 return fYUVImage;
30 } else {
31 return nullptr;
32 }
33}
34
Brian Salomonefb5f072020-07-28 21:06:43 -040035const SkImage* LazyYUVImage::getImage(GrRecordingContext* rContext) {
36 if (this->ensureYUVImage(rContext)) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040037 return fYUVImage.get();
38 } else {
39 return nullptr;
40 }
41}
42
43bool LazyYUVImage::reset(sk_sp<SkData> data) {
44 auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(data);
45 if (!codec) {
46 return false;
47 }
48
49 if (!codec->queryYUVA8(&fSizeInfo, fComponents, &fColorSpace)) {
50 return false;
51 }
52
53 fPlaneData.reset(fSizeInfo.computeTotalBytes());
54 void* planes[SkYUVASizeInfo::kMaxCount];
55 fSizeInfo.computePlanes(fPlaneData.get(), planes);
56 if (!codec->getYUVA8Planes(fSizeInfo, fComponents, planes)) {
57 return false;
58 }
59
60 for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
61 if (fSizeInfo.fSizes[i].isEmpty()) {
62 fPlanes[i].reset();
63 } else {
64 SkASSERT(planes[i]);
65 auto planeInfo = SkImageInfo::Make(fSizeInfo.fSizes[i].fWidth,
66 fSizeInfo.fSizes[i].fHeight,
67 kGray_8_SkColorType, kOpaque_SkAlphaType, nullptr);
68 fPlanes[i].reset(planeInfo, planes[i], fSizeInfo.fWidthBytes[i]);
69 }
70 }
71 // The SkPixmap data is fully configured now for MakeFromYUVAPixmaps once we get a GrContext
72 return true;
73}
74
Brian Salomonefb5f072020-07-28 21:06:43 -040075bool LazyYUVImage::ensureYUVImage(GrRecordingContext* rContext) {
76 if (!rContext) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040077 return false; // Cannot make a YUV image from planes
78 }
Brian Salomonefb5f072020-07-28 21:06:43 -040079 if (fYUVImage && fYUVImage->isValid(rContext)) {
80 return true; // Have already made a YUV image valid for this context.
Michael Ludwigd9958f82019-03-21 13:08:36 -040081 }
Brian Salomonefb5f072020-07-28 21:06:43 -040082 // Try to make a new YUV image for this context.
83 fYUVImage = SkImage::MakeFromYUVAPixmaps(rContext->priv().backdoor(),
84 fColorSpace,
85 fPlanes,
86 fComponents,
87 fSizeInfo.fSizes[0],
88 kTopLeft_GrSurfaceOrigin,
89 false,
90 false);
Michael Ludwigd9958f82019-03-21 13:08:36 -040091 return fYUVImage != nullptr;
92}
93
Robert Phillipsf105d382020-06-19 14:27:14 -040094///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips057c33f2020-07-17 11:59:01 -040095void YUVABackendReleaseContext::Unwind(GrDirectContext* dContext,
96 YUVABackendReleaseContext* beContext,
Robert Phillips98c39ba2020-06-26 10:01:19 -040097 bool fullFlush) {
98
Robert Phillipsf105d382020-06-19 14:27:14 -040099 // Some backends (e.g., Vulkan) require that all work associated w/ texture
100 // creation be completed before deleting the textures.
Robert Phillips98c39ba2020-06-26 10:01:19 -0400101 if (fullFlush) {
102 // If the release context client performed some operations other than backend texture
103 // creation then we may require a full flush to ensure that all the work is completed.
Robert Phillips057c33f2020-07-17 11:59:01 -0400104 dContext->flush();
105 dContext->submit(true);
Robert Phillips98c39ba2020-06-26 10:01:19 -0400106 } else {
Robert Phillips057c33f2020-07-17 11:59:01 -0400107 dContext->submit();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400108
109 while (!beContext->creationCompleted()) {
Robert Phillips057c33f2020-07-17 11:59:01 -0400110 dContext->checkAsyncWorkCompletion();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400111 }
112 }
Robert Phillipsf105d382020-06-19 14:27:14 -0400113
114 delete beContext;
115}
116
Robert Phillips057c33f2020-07-17 11:59:01 -0400117YUVABackendReleaseContext::YUVABackendReleaseContext(GrDirectContext* dContext)
118 : fDContext(dContext) {
Robert Phillipsf105d382020-06-19 14:27:14 -0400119}
120
121YUVABackendReleaseContext::~YUVABackendReleaseContext() {
122 for (int i = 0; i < 4; ++i) {
123 if (fBETextures[i].isValid()) {
Robert Phillips98c39ba2020-06-26 10:01:19 -0400124 SkASSERT(fCreationComplete[i]);
Robert Phillips057c33f2020-07-17 11:59:01 -0400125 fDContext->deleteBackendTexture(fBETextures[i]);
Robert Phillipsf105d382020-06-19 14:27:14 -0400126 }
127 }
128}
129
Robert Phillips98c39ba2020-06-26 10:01:19 -0400130template<int I> static void CreationComplete(void* releaseContext) {
131 auto beContext = reinterpret_cast<YUVABackendReleaseContext*>(releaseContext);
132 beContext->setCreationComplete(I);
133}
134
135GrGpuFinishedProc YUVABackendReleaseContext::CreationCompleteProc(int index) {
136 SkASSERT(index >= 0 && index < 4);
137
138 switch (index) {
139 case 0: return CreationComplete<0>;
140 case 1: return CreationComplete<1>;
141 case 2: return CreationComplete<2>;
142 case 3: return CreationComplete<3>;
143 }
144
145 SK_ABORT("Invalid YUVA Index.");
146 return nullptr;
147}
148
Michael Ludwigd9958f82019-03-21 13:08:36 -0400149} // namespace sk_gpu_test