blob: 143958d0536e6d12cf048f4e09ed37d8ecfc00f4 [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
Brian Salomon6db78b82020-07-31 08:57:48 -040018std::unique_ptr<LazyYUVImage> LazyYUVImage::Make(sk_sp<SkData> data, GrMipmapped mipmapped) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040019 std::unique_ptr<LazyYUVImage> image(new LazyYUVImage());
Brian Salomon6db78b82020-07-31 08:57:48 -040020 if (image->reset(std::move(data), mipmapped)) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040021 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
Brian Salomon6db78b82020-07-31 08:57:48 -040043bool LazyYUVImage::reset(sk_sp<SkData> data, GrMipmapped mipmapped) {
44 fMipmapped = mipmapped;
Michael Ludwigd9958f82019-03-21 13:08:36 -040045 auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(data);
46 if (!codec) {
47 return false;
48 }
49
50 if (!codec->queryYUVA8(&fSizeInfo, fComponents, &fColorSpace)) {
51 return false;
52 }
53
54 fPlaneData.reset(fSizeInfo.computeTotalBytes());
55 void* planes[SkYUVASizeInfo::kMaxCount];
56 fSizeInfo.computePlanes(fPlaneData.get(), planes);
57 if (!codec->getYUVA8Planes(fSizeInfo, fComponents, planes)) {
58 return false;
59 }
60
61 for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
62 if (fSizeInfo.fSizes[i].isEmpty()) {
63 fPlanes[i].reset();
64 } else {
65 SkASSERT(planes[i]);
66 auto planeInfo = SkImageInfo::Make(fSizeInfo.fSizes[i].fWidth,
67 fSizeInfo.fSizes[i].fHeight,
68 kGray_8_SkColorType, kOpaque_SkAlphaType, nullptr);
69 fPlanes[i].reset(planeInfo, planes[i], fSizeInfo.fWidthBytes[i]);
70 }
71 }
72 // The SkPixmap data is fully configured now for MakeFromYUVAPixmaps once we get a GrContext
73 return true;
74}
75
Brian Salomonefb5f072020-07-28 21:06:43 -040076bool LazyYUVImage::ensureYUVImage(GrRecordingContext* rContext) {
77 if (!rContext) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040078 return false; // Cannot make a YUV image from planes
79 }
Brian Salomonefb5f072020-07-28 21:06:43 -040080 if (fYUVImage && fYUVImage->isValid(rContext)) {
81 return true; // Have already made a YUV image valid for this context.
Michael Ludwigd9958f82019-03-21 13:08:36 -040082 }
Brian Salomonefb5f072020-07-28 21:06:43 -040083 // Try to make a new YUV image for this context.
84 fYUVImage = SkImage::MakeFromYUVAPixmaps(rContext->priv().backdoor(),
85 fColorSpace,
86 fPlanes,
87 fComponents,
88 fSizeInfo.fSizes[0],
89 kTopLeft_GrSurfaceOrigin,
Brian Salomon6db78b82020-07-31 08:57:48 -040090 static_cast<bool>(fMipmapped),
Brian Salomonefb5f072020-07-28 21:06:43 -040091 false);
Michael Ludwigd9958f82019-03-21 13:08:36 -040092 return fYUVImage != nullptr;
93}
94
Robert Phillipsf105d382020-06-19 14:27:14 -040095///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips057c33f2020-07-17 11:59:01 -040096void YUVABackendReleaseContext::Unwind(GrDirectContext* dContext,
97 YUVABackendReleaseContext* beContext,
Robert Phillips98c39ba2020-06-26 10:01:19 -040098 bool fullFlush) {
99
Robert Phillipsf105d382020-06-19 14:27:14 -0400100 // Some backends (e.g., Vulkan) require that all work associated w/ texture
101 // creation be completed before deleting the textures.
Robert Phillips98c39ba2020-06-26 10:01:19 -0400102 if (fullFlush) {
103 // If the release context client performed some operations other than backend texture
104 // creation then we may require a full flush to ensure that all the work is completed.
Robert Phillips057c33f2020-07-17 11:59:01 -0400105 dContext->flush();
106 dContext->submit(true);
Robert Phillips98c39ba2020-06-26 10:01:19 -0400107 } else {
Robert Phillips057c33f2020-07-17 11:59:01 -0400108 dContext->submit();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400109
110 while (!beContext->creationCompleted()) {
Robert Phillips057c33f2020-07-17 11:59:01 -0400111 dContext->checkAsyncWorkCompletion();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400112 }
113 }
Robert Phillipsf105d382020-06-19 14:27:14 -0400114
115 delete beContext;
116}
117
Robert Phillips057c33f2020-07-17 11:59:01 -0400118YUVABackendReleaseContext::YUVABackendReleaseContext(GrDirectContext* dContext)
119 : fDContext(dContext) {
Robert Phillipsf105d382020-06-19 14:27:14 -0400120}
121
122YUVABackendReleaseContext::~YUVABackendReleaseContext() {
123 for (int i = 0; i < 4; ++i) {
124 if (fBETextures[i].isValid()) {
Robert Phillips98c39ba2020-06-26 10:01:19 -0400125 SkASSERT(fCreationComplete[i]);
Robert Phillips057c33f2020-07-17 11:59:01 -0400126 fDContext->deleteBackendTexture(fBETextures[i]);
Robert Phillipsf105d382020-06-19 14:27:14 -0400127 }
128 }
129}
130
Robert Phillips98c39ba2020-06-26 10:01:19 -0400131template<int I> static void CreationComplete(void* releaseContext) {
132 auto beContext = reinterpret_cast<YUVABackendReleaseContext*>(releaseContext);
133 beContext->setCreationComplete(I);
134}
135
136GrGpuFinishedProc YUVABackendReleaseContext::CreationCompleteProc(int index) {
137 SkASSERT(index >= 0 && index < 4);
138
139 switch (index) {
140 case 0: return CreationComplete<0>;
141 case 1: return CreationComplete<1>;
142 case 2: return CreationComplete<2>;
143 case 3: return CreationComplete<3>;
144 }
145
146 SK_ABORT("Invalid YUVA Index.");
147 return nullptr;
148}
149
Michael Ludwigd9958f82019-03-21 13:08:36 -0400150} // namespace sk_gpu_test