Michael Ludwig | d9958f8 | 2019-03-21 13:08:36 -0400 | [diff] [blame] | 1 | /* |
| 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 | |
| 8 | #ifndef YUVUtils_DEFINED |
| 9 | #define YUVUtils_DEFINED |
| 10 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 11 | #include "include/core/SkImage.h" |
| 12 | #include "include/core/SkYUVAIndex.h" |
| 13 | #include "include/core/SkYUVASizeInfo.h" |
Robert Phillips | f105d38 | 2020-06-19 14:27:14 -0400 | [diff] [blame] | 14 | #include "include/gpu/GrBackendSurface.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 15 | #include "src/core/SkAutoMalloc.h" |
Michael Ludwig | d9958f8 | 2019-03-21 13:08:36 -0400 | [diff] [blame] | 16 | |
| 17 | class SkData; |
| 18 | |
| 19 | namespace sk_gpu_test { |
| 20 | |
| 21 | // Utility that decodes a JPEG but preserves the YUVA8 planes in the image, and uses |
| 22 | // MakeFromYUVAPixmaps to create a GPU multiplane YUVA image for a context. It extracts the planar |
| 23 | // data once, and lazily creates the actual SkImage when the GrContext is provided (and refreshes |
| 24 | // the image if the context has changed, as in Viewer) |
| 25 | class LazyYUVImage { |
| 26 | public: |
| 27 | // Returns null if the data could not be extracted into YUVA8 planes |
| 28 | static std::unique_ptr<LazyYUVImage> Make(sk_sp<SkData> data); |
| 29 | |
| 30 | sk_sp<SkImage> refImage(GrContext* context); |
| 31 | |
| 32 | const SkImage* getImage(GrContext* context); |
| 33 | |
| 34 | private: |
| 35 | // Decoded YUV data |
| 36 | SkYUVASizeInfo fSizeInfo; |
| 37 | SkYUVColorSpace fColorSpace; |
| 38 | SkYUVAIndex fComponents[SkYUVAIndex::kIndexCount]; |
| 39 | SkAutoMalloc fPlaneData; |
| 40 | SkPixmap fPlanes[SkYUVASizeInfo::kMaxCount]; |
| 41 | |
| 42 | // Memoized SkImage formed with planes |
| 43 | sk_sp<SkImage> fYUVImage; |
| 44 | uint32_t fOwningContextID; |
| 45 | |
| 46 | LazyYUVImage() : fOwningContextID(SK_InvalidGenID) {} |
| 47 | |
| 48 | bool reset(sk_sp<SkData> data); |
| 49 | |
| 50 | bool ensureYUVImage(GrContext* context); |
| 51 | }; |
| 52 | |
Robert Phillips | f105d38 | 2020-06-19 14:27:14 -0400 | [diff] [blame] | 53 | // A helper for managing the lifetime of backend textures for YUVA images. |
| 54 | class YUVABackendReleaseContext { |
| 55 | public: |
Robert Phillips | 98c39ba | 2020-06-26 10:01:19 -0400 | [diff] [blame] | 56 | static GrGpuFinishedProc CreationCompleteProc(int index); |
| 57 | |
Robert Phillips | f105d38 | 2020-06-19 14:27:14 -0400 | [diff] [blame] | 58 | // A stock 'TextureReleaseProc' to use with this class |
| 59 | static void Release(void* releaseContext) { |
| 60 | auto beContext = reinterpret_cast<YUVABackendReleaseContext*>(releaseContext); |
| 61 | |
| 62 | delete beContext; |
| 63 | } |
| 64 | |
| 65 | // Given how and when backend textures are created, just deleting this object often |
| 66 | // isn't enough. This helper encapsulates the extra work needed. |
Robert Phillips | 98c39ba | 2020-06-26 10:01:19 -0400 | [diff] [blame] | 67 | static void Unwind(GrContext* context, YUVABackendReleaseContext* beContext, bool fullFlush); |
Robert Phillips | f105d38 | 2020-06-19 14:27:14 -0400 | [diff] [blame] | 68 | |
| 69 | YUVABackendReleaseContext(GrContext* context); |
| 70 | ~YUVABackendReleaseContext(); |
| 71 | |
| 72 | void set(int index, const GrBackendTexture& beTex) { |
| 73 | SkASSERT(index >= 0 && index < 4); |
| 74 | SkASSERT(!fBETextures[index].isValid()); |
| 75 | SkASSERT(beTex.isValid()); |
| 76 | |
| 77 | fBETextures[index] = beTex; |
| 78 | } |
| 79 | |
Robert Phillips | 98c39ba | 2020-06-26 10:01:19 -0400 | [diff] [blame] | 80 | void setCreationComplete(int index) { |
| 81 | SkASSERT(index >= 0 && index < 4); |
| 82 | // In GL, the finished proc can fire before the backend texture is returned to the client |
| 83 | // SkASSERT(fBETextures[index].isValid()); |
| 84 | |
| 85 | fCreationComplete[index] = true; |
| 86 | } |
| 87 | |
| 88 | bool creationCompleted() const { |
| 89 | for (int i = 0; i < 4; ++i) { |
| 90 | if (fBETextures[i].isValid() && !fCreationComplete[i]) { |
| 91 | return false; |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | return true; |
| 96 | } |
| 97 | |
Robert Phillips | f105d38 | 2020-06-19 14:27:14 -0400 | [diff] [blame] | 98 | const GrBackendTexture* beTextures() const { return fBETextures; } |
| 99 | |
| 100 | const GrBackendTexture& beTexture(int index) { |
| 101 | SkASSERT(index >= 0 && index < 4); |
| 102 | SkASSERT(fBETextures[index].isValid()); |
| 103 | return fBETextures[index]; |
| 104 | } |
| 105 | |
| 106 | private: |
| 107 | GrContext* fContext; |
| 108 | GrBackendTexture fBETextures[4]; |
Robert Phillips | 98c39ba | 2020-06-26 10:01:19 -0400 | [diff] [blame] | 109 | bool fCreationComplete[4] = { false }; |
Robert Phillips | f105d38 | 2020-06-19 14:27:14 -0400 | [diff] [blame] | 110 | }; |
| 111 | |
| 112 | |
Michael Ludwig | d9958f8 | 2019-03-21 13:08:36 -0400 | [diff] [blame] | 113 | } // namespace sk_gpu_test |
| 114 | |
| 115 | #endif // YUVUtils_DEFINED |