blob: 4535d910bfa538628ccde50d3ed9bb645a706773 [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
Brian Salomonbe0e42c2020-08-27 11:00:04 -040050 SkYUVAPixmapInfo yuvaPixmapInfo;
51 if (!codec->queryYUVAInfo(&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.
78 fYUVImage = SkImage::MakeFromYUVAPixmaps(rContext->priv().backdoor(),
Brian Salomon87d42e52020-08-24 09:18:16 -040079 fPixmaps.yuvaInfo().yuvColorSpace(),
Brian Salomonbe0e42c2020-08-27 11:00:04 -040080 fPixmaps.planes().data(),
Brian Salomonefb5f072020-07-28 21:06:43 -040081 fComponents,
82 fSizeInfo.fSizes[0],
83 kTopLeft_GrSurfaceOrigin,
Brian Salomon6db78b82020-07-31 08:57:48 -040084 static_cast<bool>(fMipmapped),
Brian Salomonefb5f072020-07-28 21:06:43 -040085 false);
Michael Ludwigd9958f82019-03-21 13:08:36 -040086 return fYUVImage != nullptr;
87}
88
Robert Phillipsf105d382020-06-19 14:27:14 -040089///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips057c33f2020-07-17 11:59:01 -040090void YUVABackendReleaseContext::Unwind(GrDirectContext* dContext,
91 YUVABackendReleaseContext* beContext,
Robert Phillips98c39ba2020-06-26 10:01:19 -040092 bool fullFlush) {
93
Robert Phillipsf105d382020-06-19 14:27:14 -040094 // Some backends (e.g., Vulkan) require that all work associated w/ texture
95 // creation be completed before deleting the textures.
Robert Phillips98c39ba2020-06-26 10:01:19 -040096 if (fullFlush) {
97 // If the release context client performed some operations other than backend texture
98 // creation then we may require a full flush to ensure that all the work is completed.
Robert Phillips057c33f2020-07-17 11:59:01 -040099 dContext->flush();
100 dContext->submit(true);
Robert Phillips98c39ba2020-06-26 10:01:19 -0400101 } else {
Robert Phillips057c33f2020-07-17 11:59:01 -0400102 dContext->submit();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400103
104 while (!beContext->creationCompleted()) {
Robert Phillips057c33f2020-07-17 11:59:01 -0400105 dContext->checkAsyncWorkCompletion();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400106 }
107 }
Robert Phillipsf105d382020-06-19 14:27:14 -0400108
109 delete beContext;
110}
111
Robert Phillips057c33f2020-07-17 11:59:01 -0400112YUVABackendReleaseContext::YUVABackendReleaseContext(GrDirectContext* dContext)
113 : fDContext(dContext) {
Robert Phillipsf105d382020-06-19 14:27:14 -0400114}
115
116YUVABackendReleaseContext::~YUVABackendReleaseContext() {
117 for (int i = 0; i < 4; ++i) {
118 if (fBETextures[i].isValid()) {
Robert Phillips98c39ba2020-06-26 10:01:19 -0400119 SkASSERT(fCreationComplete[i]);
Robert Phillips057c33f2020-07-17 11:59:01 -0400120 fDContext->deleteBackendTexture(fBETextures[i]);
Robert Phillipsf105d382020-06-19 14:27:14 -0400121 }
122 }
123}
124
Robert Phillips98c39ba2020-06-26 10:01:19 -0400125template<int I> static void CreationComplete(void* releaseContext) {
126 auto beContext = reinterpret_cast<YUVABackendReleaseContext*>(releaseContext);
127 beContext->setCreationComplete(I);
128}
129
130GrGpuFinishedProc YUVABackendReleaseContext::CreationCompleteProc(int index) {
131 SkASSERT(index >= 0 && index < 4);
132
133 switch (index) {
134 case 0: return CreationComplete<0>;
135 case 1: return CreationComplete<1>;
136 case 2: return CreationComplete<2>;
137 case 3: return CreationComplete<3>;
138 }
139
140 SK_ABORT("Invalid YUVA Index.");
141 return nullptr;
142}
143
Michael Ludwigd9958f82019-03-21 13:08:36 -0400144} // namespace sk_gpu_test