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 <GrAHardwareBufferUtils.h> 20 #include <GrDirectContext.h> 21 #include <SkImage.h> 22 #include <SkSurface.h> 23 #include <sys/types.h> 24 #include <ui/GraphicTypes.h> 25 26 #include "android-base/macros.h" 27 28 #include <mutex> 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(GrDirectContext * context,AHardwareBuffer * buffer,bool isOutputBuffer,CleanupManager & cleanupMgr)83 LocalRef(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, 84 CleanupManager& cleanupMgr) { 85 mTexture = new AutoBackendTexture(context, buffer, isOutputBuffer, cleanupMgr); 86 mTexture->ref(); 87 } 88 ~LocalRef()89 ~LocalRef() { 90 if (mTexture != nullptr) { 91 mTexture->unref(true); 92 } 93 } 94 95 // Makes a new SkImage from the texture content. 96 // As SkImages are immutable but buffer content is not, we create 97 // a new SkImage every time. makeImage(ui::Dataspace dataspace,SkAlphaType alphaType,GrDirectContext * context)98 sk_sp<SkImage> makeImage(ui::Dataspace dataspace, SkAlphaType alphaType, 99 GrDirectContext* context) { 100 return mTexture->makeImage(dataspace, alphaType, context); 101 } 102 103 // Makes a new SkSurface from the texture content, if needed. getOrCreateSurface(ui::Dataspace dataspace,GrDirectContext * context)104 sk_sp<SkSurface> getOrCreateSurface(ui::Dataspace dataspace, GrDirectContext* context) { 105 return mTexture->getOrCreateSurface(dataspace, context); 106 } 107 colorType()108 SkColorType colorType() const { return mTexture->mColorType; } 109 110 DISALLOW_COPY_AND_ASSIGN(LocalRef); 111 112 private: 113 AutoBackendTexture* mTexture = nullptr; 114 }; 115 116 private: 117 // Creates a GrBackendTexture whose contents come from the provided buffer. 118 AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, 119 CleanupManager& cleanupMgr); 120 121 // The only way to invoke dtor is with unref, when mUsageCount is 0. 122 ~AutoBackendTexture(); 123 ref()124 void ref() { mUsageCount++; } 125 126 // releaseLocalResources is true if the underlying SkImage and SkSurface 127 // should be deleted from local tracking. 128 void unref(bool releaseLocalResources); 129 130 // Makes a new SkImage from the texture content. 131 // As SkImages are immutable but buffer content is not, we create 132 // a new SkImage every time. 133 sk_sp<SkImage> makeImage(ui::Dataspace dataspace, SkAlphaType alphaType, 134 GrDirectContext* context); 135 136 // Makes a new SkSurface from the texture content, if needed. 137 sk_sp<SkSurface> getOrCreateSurface(ui::Dataspace dataspace, GrDirectContext* context); 138 139 GrBackendTexture mBackendTexture; 140 GrAHardwareBufferUtils::DeleteImageProc mDeleteProc; 141 GrAHardwareBufferUtils::UpdateImageProc mUpdateProc; 142 GrAHardwareBufferUtils::TexImageCtx mImageCtx; 143 144 CleanupManager& mCleanupMgr; 145 146 static void releaseSurfaceProc(SkSurface::ReleaseContext releaseContext); 147 static void releaseImageProc(SkImage::ReleaseContext releaseContext); 148 149 int mUsageCount = 0; 150 151 const bool mIsOutputBuffer; 152 sk_sp<SkImage> mImage = nullptr; 153 sk_sp<SkSurface> mSurface = nullptr; 154 ui::Dataspace mDataspace = ui::Dataspace::UNKNOWN; 155 SkColorType mColorType = kUnknown_SkColorType; 156 }; 157 158 } // namespace skia 159 } // namespace renderengine 160 } // namespace android 161