blob: b7965857045ce46285d4e29804d98a2009b1ed24 [file] [log] [blame]
Stan Ilievaaa9e832019-09-17 14:07:23 -04001/*
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
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +000019#include <SkImage.h>
20#include <include/gpu/ganesh/SkImageGanesh.h>
Stan Ilievaaa9e832019-09-17 14:07:23 -040021#include "renderthread/RenderThread.h"
22#include "utils/Color.h"
23#include "utils/PaintUtils.h"
24
25using namespace android::uirenderer::renderthread;
26
27namespace android {
28namespace uirenderer {
29
Adlai Hollerf8c434e2020-07-27 11:42:45 -040030AutoBackendTextureRelease::AutoBackendTextureRelease(GrDirectContext* context,
31 AHardwareBuffer* buffer) {
Stan Ilievaaa9e832019-09-17 14:07:23 -040032 AHardwareBuffer_Desc desc;
33 AHardwareBuffer_describe(buffer, &desc);
34 bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
35 GrBackendFormat backendFormat =
36 GrAHardwareBufferUtils::GetBackendFormat(context, buffer, desc.format, false);
Nolan Scobie2163e412022-10-24 19:57:43 -040037 LOG_ALWAYS_FATAL_IF(!backendFormat.isValid(),
38 __FILE__ " Invalid GrBackendFormat. GrBackendApi==%" PRIu32
39 ", AHardwareBuffer_Format==%" PRIu32 ".",
40 static_cast<int>(context->backend()), desc.format);
Stan Ilievaaa9e832019-09-17 14:07:23 -040041 mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture(
42 context, buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx,
43 createProtectedImage, backendFormat, false);
Nolan Scobie2163e412022-10-24 19:57:43 -040044 LOG_ALWAYS_FATAL_IF(!mBackendTexture.isValid(),
45 __FILE__ " Invalid GrBackendTexture. Width==%" PRIu32 ", height==%" PRIu32
46 ", protected==%d",
47 desc.width, desc.height, createProtectedImage);
Stan Ilievaaa9e832019-09-17 14:07:23 -040048}
49
50void AutoBackendTextureRelease::unref(bool releaseImage) {
51 if (!RenderThread::isCurrent()) {
52 // EGLImage needs to be destroyed on RenderThread to prevent memory leak.
53 // ~SkImage dtor for both pipelines needs to be invoked on RenderThread, because it is not
54 // thread safe.
55 RenderThread::getInstance().queue().post([this, releaseImage]() { unref(releaseImage); });
56 return;
57 }
58
59 if (releaseImage) {
60 mImage.reset();
61 }
62
63 mUsageCount--;
64 if (mUsageCount <= 0) {
65 if (mBackendTexture.isValid()) {
66 mDeleteProc(mImageCtx);
67 mBackendTexture = {};
68 }
69 delete this;
70 }
71}
72
73// releaseProc is invoked by SkImage, when texture is no longer in use.
74// "releaseContext" contains an "AutoBackendTextureRelease*".
Kevin Lubick36e81af2023-05-11 14:58:45 +000075static void releaseProc(SkImages::ReleaseContext releaseContext) {
Stan Ilievaaa9e832019-09-17 14:07:23 -040076 AutoBackendTextureRelease* textureRelease =
77 reinterpret_cast<AutoBackendTextureRelease*>(releaseContext);
78 textureRelease->unref(false);
79}
80
Adlai Hollerf8c434e2020-07-27 11:42:45 -040081void AutoBackendTextureRelease::makeImage(AHardwareBuffer* buffer,
82 android_dataspace dataspace,
83 GrDirectContext* context) {
Stan Ilievaaa9e832019-09-17 14:07:23 -040084 AHardwareBuffer_Desc desc;
85 AHardwareBuffer_describe(buffer, &desc);
86 SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format);
Nolan Scobie2163e412022-10-24 19:57:43 -040087 // The following ref will be counteracted by Skia calling releaseProc, either during
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +000088 // BorrowTextureFrom if there is a failure, or later when SkImage is discarded. It must
89 // be called before BorrowTextureFrom, otherwise Skia may remove HWUI's ref on failure.
Nolan Scobie2163e412022-10-24 19:57:43 -040090 ref();
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +000091 mImage = SkImages::BorrowTextureFrom(
Stan Ilievaaa9e832019-09-17 14:07:23 -040092 context, mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType,
93 uirenderer::DataSpaceToColorSpace(dataspace), releaseProc, this);
Stan Ilievaaa9e832019-09-17 14:07:23 -040094}
95
Adlai Hollerf8c434e2020-07-27 11:42:45 -040096void AutoBackendTextureRelease::newBufferContent(GrDirectContext* context) {
Stan Ilievaaa9e832019-09-17 14:07:23 -040097 if (mBackendTexture.isValid()) {
98 mUpdateProc(mImageCtx, context);
99 }
100}
101
Greg Daniel27e1fa22021-05-26 09:24:15 -0400102void AutoBackendTextureRelease::releaseQueueOwnership(GrDirectContext* context) {
103 if (!context) {
104 return;
105 }
106
107 LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan);
108 if (mBackendTexture.isValid()) {
109 // Passing in VK_IMAGE_LAYOUT_UNDEFINED means we keep the old layout.
110 GrBackendSurfaceMutableState newState(VK_IMAGE_LAYOUT_UNDEFINED,
111 VK_QUEUE_FAMILY_FOREIGN_EXT);
112
113 // The unref for this ref happens in the releaseProc passed into setBackendTextureState. The
114 // releaseProc callback will be made when the work to set the new state has finished on the
115 // gpu.
116 ref();
117 // Note that we don't have an explicit call to set the backend texture back onto the
118 // graphics queue when we use the VkImage again. Internally, Skia will notice that the image
119 // is not on the graphics queue and will do the transition automatically.
120 context->setBackendTextureState(mBackendTexture, newState, nullptr, releaseProc, this);
121 }
122}
123
Stan Ilievaaa9e832019-09-17 14:07:23 -0400124} /* namespace uirenderer */
125} /* namespace android */