blob: b8dcc8533ca44ef491e0c7d1f52b626f1052aff5 [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"
11#include "include/gpu/GrContext.h"
12#include "src/codec/SkCodecImageGenerator.h"
13#include "src/gpu/GrContextPriv.h"
Michael Ludwigd9958f82019-03-21 13:08:36 -040014
15namespace sk_gpu_test {
16
17std::unique_ptr<LazyYUVImage> LazyYUVImage::Make(sk_sp<SkData> data) {
18 std::unique_ptr<LazyYUVImage> image(new LazyYUVImage());
19 if (image->reset(std::move(data))) {
20 return image;
21 } else {
22 return nullptr;
23 }
24}
25
26sk_sp<SkImage> LazyYUVImage::refImage(GrContext* context) {
27 if (this->ensureYUVImage(context)) {
28 return fYUVImage;
29 } else {
30 return nullptr;
31 }
32}
33
34const SkImage* LazyYUVImage::getImage(GrContext* context) {
35 if (this->ensureYUVImage(context)) {
36 return fYUVImage.get();
37 } else {
38 return nullptr;
39 }
40}
41
42bool LazyYUVImage::reset(sk_sp<SkData> data) {
43 auto codec = SkCodecImageGenerator::MakeFromEncodedCodec(data);
44 if (!codec) {
45 return false;
46 }
47
48 if (!codec->queryYUVA8(&fSizeInfo, fComponents, &fColorSpace)) {
49 return false;
50 }
51
52 fPlaneData.reset(fSizeInfo.computeTotalBytes());
53 void* planes[SkYUVASizeInfo::kMaxCount];
54 fSizeInfo.computePlanes(fPlaneData.get(), planes);
55 if (!codec->getYUVA8Planes(fSizeInfo, fComponents, planes)) {
56 return false;
57 }
58
59 for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
60 if (fSizeInfo.fSizes[i].isEmpty()) {
61 fPlanes[i].reset();
62 } else {
63 SkASSERT(planes[i]);
64 auto planeInfo = SkImageInfo::Make(fSizeInfo.fSizes[i].fWidth,
65 fSizeInfo.fSizes[i].fHeight,
66 kGray_8_SkColorType, kOpaque_SkAlphaType, nullptr);
67 fPlanes[i].reset(planeInfo, planes[i], fSizeInfo.fWidthBytes[i]);
68 }
69 }
70 // The SkPixmap data is fully configured now for MakeFromYUVAPixmaps once we get a GrContext
71 return true;
72}
73
74bool LazyYUVImage::ensureYUVImage(GrContext* context) {
75 if (!context) {
76 return false; // Cannot make a YUV image from planes
77 }
78 if (context->priv().contextID() == fOwningContextID) {
79 return fYUVImage != nullptr; // Have already made a YUV image (or tried and failed)
80 }
81 // Must make a new YUV image
82 fYUVImage = SkImage::MakeFromYUVAPixmaps(context, fColorSpace, fPlanes, fComponents,
83 fSizeInfo.fSizes[0], kTopLeft_GrSurfaceOrigin, false, false);
84 fOwningContextID = context->priv().contextID();
85 return fYUVImage != nullptr;
86}
87
Robert Phillipsf105d382020-06-19 14:27:14 -040088///////////////////////////////////////////////////////////////////////////////////////////////////
Robert Phillips98c39ba2020-06-26 10:01:19 -040089void YUVABackendReleaseContext::Unwind(GrContext* context, YUVABackendReleaseContext* beContext,
90 bool fullFlush) {
91
Robert Phillipsf105d382020-06-19 14:27:14 -040092 // Some backends (e.g., Vulkan) require that all work associated w/ texture
93 // creation be completed before deleting the textures.
Robert Phillips98c39ba2020-06-26 10:01:19 -040094
95 if (fullFlush) {
96 // If the release context client performed some operations other than backend texture
97 // creation then we may require a full flush to ensure that all the work is completed.
98 GrFlushInfo flushInfoSyncCpu;
99 flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
100 context->flush(flushInfoSyncCpu);
101 context->submit(true);
102 } else {
103 context->submit();
104
105 while (!beContext->creationCompleted()) {
106 context->checkAsyncWorkCompletion();
107 }
108 }
Robert Phillipsf105d382020-06-19 14:27:14 -0400109
110 delete beContext;
111}
112
113YUVABackendReleaseContext::YUVABackendReleaseContext(GrContext* context) : fContext(context) {
114 SkASSERT(context->priv().getGpu());
115 SkASSERT(context->priv().asDirectContext());
116}
117
118YUVABackendReleaseContext::~YUVABackendReleaseContext() {
119 for (int i = 0; i < 4; ++i) {
120 if (fBETextures[i].isValid()) {
Robert Phillips98c39ba2020-06-26 10:01:19 -0400121 SkASSERT(fCreationComplete[i]);
Robert Phillipsf105d382020-06-19 14:27:14 -0400122 fContext->deleteBackendTexture(fBETextures[i]);
123 }
124 }
125}
126
Robert Phillips98c39ba2020-06-26 10:01:19 -0400127template<int I> static void CreationComplete(void* releaseContext) {
128 auto beContext = reinterpret_cast<YUVABackendReleaseContext*>(releaseContext);
129 beContext->setCreationComplete(I);
130}
131
132GrGpuFinishedProc YUVABackendReleaseContext::CreationCompleteProc(int index) {
133 SkASSERT(index >= 0 && index < 4);
134
135 switch (index) {
136 case 0: return CreationComplete<0>;
137 case 1: return CreationComplete<1>;
138 case 2: return CreationComplete<2>;
139 case 3: return CreationComplete<3>;
140 }
141
142 SK_ABORT("Invalid YUVA Index.");
143 return nullptr;
144}
145
Michael Ludwigd9958f82019-03-21 13:08:36 -0400146} // namespace sk_gpu_test