1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <GrDirectContext.h> 20 #include <SkImage.h> 21 #include <SkSurface.h> 22 #include <sys/types.h> 23 #include <ui/GraphicTypes.h> 24 25 #include "android-base/macros.h" 26 #include "compat/SkiaBackendTexture.h" 27 28 #include <memory> 29 #include <vector> 30 31 namespace android { 32 namespace renderengine { 33 namespace skia { 34 35 /** 36 * AutoBackendTexture manages GPU image lifetime. It is a ref-counted object 37 * that keeps GPU resources alive until the last SkImage or SkSurface object using them is 38 * destroyed. 39 */ 40 class AutoBackendTexture { 41 public: 42 // Manager class that is responsible for the immediate or deferred cleanup 43 // of AutoBackendTextures. Clients of AutoBackendTexture are responsible for 44 // ensuring that access to this class is thread safe. Clients also control when 45 // the resources are reclaimed by setting the manager into deferred mode. 46 class CleanupManager { 47 public: 48 CleanupManager() = default; add(AutoBackendTexture * abt)49 void add(AutoBackendTexture* abt) { 50 if (mDeferCleanup) { 51 mCleanupList.push_back(abt); 52 } else { 53 delete abt; 54 } 55 } 56 setDeferredStatus(bool enabled)57 void setDeferredStatus(bool enabled) { mDeferCleanup = enabled; } 58 isEmpty()59 bool isEmpty() const { return mCleanupList.empty(); } 60 61 // If any AutoBackedTextures were added while in deferred mode this method 62 // will ensure they are deleted before returning. It must only be called 63 // on the thread where the GPU context that created the AutoBackedTexture 64 // is active. cleanup()65 void cleanup() { 66 for (auto abt : mCleanupList) { 67 delete abt; 68 } 69 mCleanupList.clear(); 70 } 71 72 private: 73 DISALLOW_COPY_AND_ASSIGN(CleanupManager); 74 bool mDeferCleanup = false; 75 std::vector<AutoBackendTexture*> mCleanupList; 76 }; 77 78 // Local reference that supports RAII-style management of an AutoBackendTexture 79 // AutoBackendTexture by itself can't be managed in a similar fashion because 80 // of shared ownership with Skia objects, so we wrap it here instead. 81 class LocalRef { 82 public: LocalRef(std::unique_ptr<SkiaBackendTexture> backendTexture,CleanupManager & cleanupMgr)83 LocalRef(std::unique_ptr<SkiaBackendTexture> backendTexture, CleanupManager& cleanupMgr) { 84 mTexture = new AutoBackendTexture(std::move(backendTexture), cleanupMgr); 85 mTexture->ref(); 86 } 87 ~LocalRef()88 ~LocalRef() { 89 if (mTexture != nullptr) { 90 mTexture->unref(true); 91 } 92 } 93 94 // Makes a new SkImage from the texture content. 95 // As SkImages are immutable but buffer content is not, we create 96 // a new SkImage every time. makeImage(ui::Dataspace dataspace,SkAlphaType alphaType)97 sk_sp<SkImage> makeImage(ui::Dataspace dataspace, SkAlphaType alphaType) { 98 return mTexture->makeImage(dataspace, alphaType); 99 } 100 101 // Makes a new SkSurface from the texture content, if needed. getOrCreateSurface(ui::Dataspace dataspace)102 sk_sp<SkSurface> getOrCreateSurface(ui::Dataspace dataspace) { 103 return mTexture->getOrCreateSurface(dataspace); 104 } 105 colorType()106 SkColorType colorType() const { return mTexture->mBackendTexture->internalColorType(); } 107 108 DISALLOW_COPY_AND_ASSIGN(LocalRef); 109 110 private: 111 AutoBackendTexture* mTexture = nullptr; 112 }; 113 114 private: 115 DISALLOW_COPY_AND_ASSIGN(AutoBackendTexture); 116 117 // Creates an AutoBackendTexture to manage the lifecycle of a given SkiaBackendTexture, which is 118 // in turn backed by an underlying backend-specific texture type. 119 AutoBackendTexture(std::unique_ptr<SkiaBackendTexture> backendTexture, 120 CleanupManager& cleanupMgr); 121 122 // The only way to invoke dtor is with unref, when mUsageCount is 0. 123 ~AutoBackendTexture() = default; 124 ref()125 void ref() { mUsageCount++; } 126 127 // releaseLocalResources is true if the underlying SkImage and SkSurface 128 // should be deleted from local tracking. 129 void unref(bool releaseLocalResources); 130 131 // Makes a new SkImage from the texture content. 132 // As SkImages are immutable but buffer content is not, we create 133 // a new SkImage every time. 134 sk_sp<SkImage> makeImage(ui::Dataspace dataspace, SkAlphaType alphaType); 135 136 // Makes a new SkSurface from the texture content, if needed. 137 sk_sp<SkSurface> getOrCreateSurface(ui::Dataspace dataspace); 138 139 CleanupManager& mCleanupMgr; 140 141 static void releaseSurfaceProc(SkSurface::ReleaseContext releaseContext); 142 static void releaseImageProc(SkImages::ReleaseContext releaseContext); 143 144 std::unique_ptr<SkiaBackendTexture> mBackendTexture; 145 int mUsageCount = 0; 146 sk_sp<SkImage> mImage = nullptr; 147 sk_sp<SkSurface> mSurface = nullptr; 148 ui::Dataspace mDataspace = ui::Dataspace::UNKNOWN; 149 }; 150 151 } // namespace skia 152 } // namespace renderengine 153 } // namespace android 154