| Stan Iliev | aaa9e83 | 2019-09-17 14:07:23 -0400 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2019 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 | #include "AutoBackendTextureRelease.h" | 
 | 18 |  | 
 | 19 | #include "renderthread/RenderThread.h" | 
 | 20 | #include "utils/Color.h" | 
 | 21 | #include "utils/PaintUtils.h" | 
 | 22 |  | 
 | 23 | using namespace android::uirenderer::renderthread; | 
 | 24 |  | 
 | 25 | namespace android { | 
 | 26 | namespace uirenderer { | 
 | 27 |  | 
| Adlai Holler | f8c434e | 2020-07-27 11:42:45 -0400 | [diff] [blame] | 28 | AutoBackendTextureRelease::AutoBackendTextureRelease(GrDirectContext* context, | 
 | 29 |                                                      AHardwareBuffer* buffer) { | 
| Stan Iliev | aaa9e83 | 2019-09-17 14:07:23 -0400 | [diff] [blame] | 30 |     AHardwareBuffer_Desc desc; | 
 | 31 |     AHardwareBuffer_describe(buffer, &desc); | 
 | 32 |     bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT); | 
 | 33 |     GrBackendFormat backendFormat = | 
 | 34 |             GrAHardwareBufferUtils::GetBackendFormat(context, buffer, desc.format, false); | 
 | 35 |     mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture( | 
 | 36 |             context, buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx, | 
 | 37 |             createProtectedImage, backendFormat, false); | 
 | 38 | } | 
 | 39 |  | 
 | 40 | void AutoBackendTextureRelease::unref(bool releaseImage) { | 
 | 41 |     if (!RenderThread::isCurrent()) { | 
 | 42 |         // EGLImage needs to be destroyed on RenderThread to prevent memory leak. | 
 | 43 |         // ~SkImage dtor for both pipelines needs to be invoked on RenderThread, because it is not | 
 | 44 |         // thread safe. | 
 | 45 |         RenderThread::getInstance().queue().post([this, releaseImage]() { unref(releaseImage); }); | 
 | 46 |         return; | 
 | 47 |     } | 
 | 48 |  | 
 | 49 |     if (releaseImage) { | 
 | 50 |         mImage.reset(); | 
 | 51 |     } | 
 | 52 |  | 
 | 53 |     mUsageCount--; | 
 | 54 |     if (mUsageCount <= 0) { | 
 | 55 |         if (mBackendTexture.isValid()) { | 
 | 56 |             mDeleteProc(mImageCtx); | 
 | 57 |             mBackendTexture = {}; | 
 | 58 |         } | 
 | 59 |         delete this; | 
 | 60 |     } | 
 | 61 | } | 
 | 62 |  | 
 | 63 | // releaseProc is invoked by SkImage, when texture is no longer in use. | 
 | 64 | // "releaseContext" contains an "AutoBackendTextureRelease*". | 
 | 65 | static void releaseProc(SkImage::ReleaseContext releaseContext) { | 
 | 66 |     AutoBackendTextureRelease* textureRelease = | 
 | 67 |             reinterpret_cast<AutoBackendTextureRelease*>(releaseContext); | 
 | 68 |     textureRelease->unref(false); | 
 | 69 | } | 
 | 70 |  | 
| Adlai Holler | f8c434e | 2020-07-27 11:42:45 -0400 | [diff] [blame] | 71 | void AutoBackendTextureRelease::makeImage(AHardwareBuffer* buffer, | 
 | 72 |                                           android_dataspace dataspace, | 
 | 73 |                                           GrDirectContext* context) { | 
| Stan Iliev | aaa9e83 | 2019-09-17 14:07:23 -0400 | [diff] [blame] | 74 |     AHardwareBuffer_Desc desc; | 
 | 75 |     AHardwareBuffer_describe(buffer, &desc); | 
 | 76 |     SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format); | 
 | 77 |     mImage = SkImage::MakeFromTexture( | 
 | 78 |             context, mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType, | 
 | 79 |             uirenderer::DataSpaceToColorSpace(dataspace), releaseProc, this); | 
 | 80 |     if (mImage.get()) { | 
 | 81 |         // The following ref will be counteracted by releaseProc, when SkImage is discarded. | 
 | 82 |         ref(); | 
 | 83 |     } | 
 | 84 | } | 
 | 85 |  | 
| Adlai Holler | f8c434e | 2020-07-27 11:42:45 -0400 | [diff] [blame] | 86 | void AutoBackendTextureRelease::newBufferContent(GrDirectContext* context) { | 
| Stan Iliev | aaa9e83 | 2019-09-17 14:07:23 -0400 | [diff] [blame] | 87 |     if (mBackendTexture.isValid()) { | 
 | 88 |         mUpdateProc(mImageCtx, context); | 
 | 89 |     } | 
 | 90 | } | 
 | 91 |  | 
| Greg Daniel | 27e1fa2 | 2021-05-26 09:24:15 -0400 | [diff] [blame] | 92 | void AutoBackendTextureRelease::releaseQueueOwnership(GrDirectContext* context) { | 
 | 93 |     if (!context) { | 
 | 94 |         return; | 
 | 95 |     } | 
 | 96 |  | 
 | 97 |     LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan); | 
 | 98 |     if (mBackendTexture.isValid()) { | 
 | 99 |         // Passing in VK_IMAGE_LAYOUT_UNDEFINED means we keep the old layout. | 
 | 100 |         GrBackendSurfaceMutableState newState(VK_IMAGE_LAYOUT_UNDEFINED, | 
 | 101 |                                               VK_QUEUE_FAMILY_FOREIGN_EXT); | 
 | 102 |  | 
 | 103 |         // The unref for this ref happens in the releaseProc passed into setBackendTextureState. The | 
 | 104 |         // releaseProc callback will be made when the work to set the new state has finished on the | 
 | 105 |         // gpu. | 
 | 106 |         ref(); | 
 | 107 |         // Note that we don't have an explicit call to set the backend texture back onto the | 
 | 108 |         // graphics queue when we use the VkImage again. Internally, Skia will notice that the image | 
 | 109 |         // is not on the graphics queue and will do the transition automatically. | 
 | 110 |         context->setBackendTextureState(mBackendTexture, newState, nullptr, releaseProc, this); | 
 | 111 |     } | 
 | 112 | } | 
 | 113 |  | 
| Stan Iliev | aaa9e83 | 2019-09-17 14:07:23 -0400 | [diff] [blame] | 114 | } /* namespace uirenderer */ | 
 | 115 | } /* namespace android */ |