blob: bae564dcc15d8397dc90b80647bba639315c1fbf [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"
Robert Phillips057c33f2020-07-17 11:59:01 -040011#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#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 Phillips057c33f2020-07-17 11:59:01 -040089void YUVABackendReleaseContext::Unwind(GrDirectContext* dContext,
90 YUVABackendReleaseContext* beContext,
Robert Phillips98c39ba2020-06-26 10:01:19 -040091 bool fullFlush) {
92
Robert Phillipsf105d382020-06-19 14:27:14 -040093 // Some backends (e.g., Vulkan) require that all work associated w/ texture
94 // creation be completed before deleting the textures.
Robert Phillips98c39ba2020-06-26 10:01:19 -040095 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.
Robert Phillips057c33f2020-07-17 11:59:01 -040098 dContext->flush();
99 dContext->submit(true);
Robert Phillips98c39ba2020-06-26 10:01:19 -0400100 } else {
Robert Phillips057c33f2020-07-17 11:59:01 -0400101 dContext->submit();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400102
103 while (!beContext->creationCompleted()) {
Robert Phillips057c33f2020-07-17 11:59:01 -0400104 dContext->checkAsyncWorkCompletion();
Robert Phillips98c39ba2020-06-26 10:01:19 -0400105 }
106 }
Robert Phillipsf105d382020-06-19 14:27:14 -0400107
108 delete beContext;
109}
110
Robert Phillips057c33f2020-07-17 11:59:01 -0400111YUVABackendReleaseContext::YUVABackendReleaseContext(GrDirectContext* dContext)
112 : fDContext(dContext) {
Robert Phillipsf105d382020-06-19 14:27:14 -0400113}
114
115YUVABackendReleaseContext::~YUVABackendReleaseContext() {
116 for (int i = 0; i < 4; ++i) {
117 if (fBETextures[i].isValid()) {
Robert Phillips98c39ba2020-06-26 10:01:19 -0400118 SkASSERT(fCreationComplete[i]);
Robert Phillips057c33f2020-07-17 11:59:01 -0400119 fDContext->deleteBackendTexture(fBETextures[i]);
Robert Phillipsf105d382020-06-19 14:27:14 -0400120 }
121 }
122}
123
Robert Phillips98c39ba2020-06-26 10:01:19 -0400124template<int I> static void CreationComplete(void* releaseContext) {
125 auto beContext = reinterpret_cast<YUVABackendReleaseContext*>(releaseContext);
126 beContext->setCreationComplete(I);
127}
128
129GrGpuFinishedProc YUVABackendReleaseContext::CreationCompleteProc(int index) {
130 SkASSERT(index >= 0 && index < 4);
131
132 switch (index) {
133 case 0: return CreationComplete<0>;
134 case 1: return CreationComplete<1>;
135 case 2: return CreationComplete<2>;
136 case 3: return CreationComplete<3>;
137 }
138
139 SK_ABORT("Invalid YUVA Index.");
140 return nullptr;
141}
142
Michael Ludwigd9958f82019-03-21 13:08:36 -0400143} // namespace sk_gpu_test