blob: 4e8ad248e5e9ebde0bc83b775a6cd3c3cf62f405 [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"
Adlai Hollera0693042020-10-14 11:23:11 -040013#include "src/gpu/GrDirectContextPriv.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
Brian Salomonbe0e42c2020-08-27 11:00:04 -040050 SkYUVAPixmapInfo yuvaPixmapInfo;
Brian Salomon59c60b02020-09-01 15:01:15 -040051 if (!codec->queryYUVAInfo(SkYUVAPixmapInfo::SupportedDataTypes::All(), &yuvaPixmapInfo)) {
Brian Salomon87d42e52020-08-24 09:18:16 -040052 return false;
53 }
Brian Salomonbe0e42c2020-08-27 11:00:04 -040054 fPixmaps = SkYUVAPixmaps::Allocate(yuvaPixmapInfo);
Brian Salomon87d42e52020-08-24 09:18:16 -040055 if (!fPixmaps.isValid()) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040056 return false;
57 }
58
Brian Salomonbe0e42c2020-08-27 11:00:04 -040059 if (!codec->getYUVAPlanes(fPixmaps)) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040060 return false;
61 }
62
Brian Salomon87d42e52020-08-24 09:18:16 -040063 if (!fPixmaps.toLegacy(&fSizeInfo, fComponents)) {
64 return false;
Michael Ludwigd9958f82019-03-21 13:08:36 -040065 }
66 // The SkPixmap data is fully configured now for MakeFromYUVAPixmaps once we get a GrContext
67 return true;
68}
69
Brian Salomonefb5f072020-07-28 21:06:43 -040070bool LazyYUVImage::ensureYUVImage(GrRecordingContext* rContext) {
71 if (!rContext) {
Michael Ludwigd9958f82019-03-21 13:08:36 -040072 return false; // Cannot make a YUV image from planes
73 }
Brian Salomonefb5f072020-07-28 21:06:43 -040074 if (fYUVImage && fYUVImage->isValid(rContext)) {
75 return true; // Have already made a YUV image valid for this context.
Michael Ludwigd9958f82019-03-21 13:08:36 -040076 }
Brian Salomonefb5f072020-07-28 21:06:43 -040077 // Try to make a new YUV image for this context.
Brian Salomonc2a9a972020-09-15 11:24:28 -040078 fYUVImage = SkImage::MakeFromYUVAPixmaps(rContext, fPixmaps, fMipmapped, false, nullptr);
Michael Ludwigd9958f82019-03-21 13:08:36 -040079 return fYUVImage != nullptr;
80}
81
Robert Phillipsf105d382020-06-19 14:27:14 -040082///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips057c33f2020-07-17 11:59:01 -040083void YUVABackendReleaseContext::Unwind(GrDirectContext* dContext,
84 YUVABackendReleaseContext* beContext,
Robert Phillips98c39ba2020-06-26 10:01:19 -040085 bool fullFlush) {
86
Robert Phillipsf105d382020-06-19 14:27:14 -040087 // Some backends (e.g., Vulkan) require that all work associated w/ texture
88 // creation be completed before deleting the textures.
Robert Phillips98c39ba2020-06-26 10:01:19 -040089 if (fullFlush) {
90 // If the release context client performed some operations other than backend texture
91 // creation then we may require a full flush to ensure that all the work is completed.
Robert Phillips057c33f2020-07-17 11:59:01 -040092 dContext->flush();
93 dContext->submit(true);
Robert Phillips98c39ba2020-06-26 10:01:19 -040094 } else {
Robert Phillips057c33f2020-07-17 11:59:01 -040095 dContext->submit();
Robert Phillips98c39ba2020-06-26 10:01:19 -040096
97 while (!beContext->creationCompleted()) {
Robert Phillips057c33f2020-07-17 11:59:01 -040098 dContext->checkAsyncWorkCompletion();
Robert Phillips98c39ba2020-06-26 10:01:19 -040099 }
100 }
Robert Phillipsf105d382020-06-19 14:27:14 -0400101
102 delete beContext;
103}
104
Robert Phillips057c33f2020-07-17 11:59:01 -0400105YUVABackendReleaseContext::YUVABackendReleaseContext(GrDirectContext* dContext)
106 : fDContext(dContext) {
Robert Phillipsf105d382020-06-19 14:27:14 -0400107}
108
109YUVABackendReleaseContext::~YUVABackendReleaseContext() {
110 for (int i = 0; i < 4; ++i) {
111 if (fBETextures[i].isValid()) {
Robert Phillips98c39ba2020-06-26 10:01:19 -0400112 SkASSERT(fCreationComplete[i]);
Robert Phillips057c33f2020-07-17 11:59:01 -0400113 fDContext->deleteBackendTexture(fBETextures[i]);
Robert Phillipsf105d382020-06-19 14:27:14 -0400114 }
115 }
116}
117
Robert Phillips98c39ba2020-06-26 10:01:19 -0400118template<int I> static void CreationComplete(void* releaseContext) {
119 auto beContext = reinterpret_cast<YUVABackendReleaseContext*>(releaseContext);
120 beContext->setCreationComplete(I);
121}
122
123GrGpuFinishedProc YUVABackendReleaseContext::CreationCompleteProc(int index) {
124 SkASSERT(index >= 0 && index < 4);
125
126 switch (index) {
127 case 0: return CreationComplete<0>;
128 case 1: return CreationComplete<1>;
129 case 2: return CreationComplete<2>;
130 case 3: return CreationComplete<3>;
131 }
132
133 SK_ABORT("Invalid YUVA Index.");
134 return nullptr;
135}
136
Michael Ludwigd9958f82019-03-21 13:08:36 -0400137} // namespace sk_gpu_test