blob: 430519606d9be690377616cf0c70d625de3711c6 [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>
Brian Osmanc2054ae2023-08-16 17:51:07 +000020#include <include/gpu/MutableTextureState.h>
Nolan Scobie572d8012024-08-30 13:43:34 -040021#include <include/gpu/ganesh/GrBackendSurface.h>
22#include <include/gpu/ganesh/GrDirectContext.h>
23#include <include/gpu/ganesh/SkImageGanesh.h>
Kevin Lubick41403bd2024-01-22 17:28:40 +000024#include <include/gpu/vk/VulkanMutableTextureState.h>
Nolan Scobie572d8012024-08-30 13:43:34 -040025
Stan Ilievaaa9e832019-09-17 14:07:23 -040026#include "renderthread/RenderThread.h"
27#include "utils/Color.h"
28#include "utils/PaintUtils.h"
29
30using namespace android::uirenderer::renderthread;
31
32namespace android {
33namespace uirenderer {
34
Adlai Hollerf8c434e2020-07-27 11:42:45 -040035AutoBackendTextureRelease::AutoBackendTextureRelease(GrDirectContext* context,
36 AHardwareBuffer* buffer) {
Stan Ilievaaa9e832019-09-17 14:07:23 -040037 AHardwareBuffer_Desc desc;
38 AHardwareBuffer_describe(buffer, &desc);
39 bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
Kevin Lubick60d06862023-08-07 15:29:12 +000040
41 GrBackendFormat backendFormat;
42 GrBackendApi backend = context->backend();
43 if (backend == GrBackendApi::kOpenGL) {
44 backendFormat =
45 GrAHardwareBufferUtils::GetGLBackendFormat(context, desc.format, false);
46 mBackendTexture =
47 GrAHardwareBufferUtils::MakeGLBackendTexture(context,
48 buffer,
49 desc.width,
50 desc.height,
51 &mDeleteProc,
52 &mUpdateProc,
53 &mImageCtx,
54 createProtectedImage,
55 backendFormat,
56 false);
57 } else if (backend == GrBackendApi::kVulkan) {
58 backendFormat =
59 GrAHardwareBufferUtils::GetVulkanBackendFormat(context,
60 buffer,
61 desc.format,
62 false);
63 mBackendTexture =
64 GrAHardwareBufferUtils::MakeVulkanBackendTexture(context,
65 buffer,
66 desc.width,
67 desc.height,
68 &mDeleteProc,
69 &mUpdateProc,
70 &mImageCtx,
71 createProtectedImage,
72 backendFormat,
73 false);
74 } else {
75 LOG_ALWAYS_FATAL("Unexpected backend %d", backend);
76 }
Nolan Scobie2163e412022-10-24 19:57:43 -040077 LOG_ALWAYS_FATAL_IF(!backendFormat.isValid(),
78 __FILE__ " Invalid GrBackendFormat. GrBackendApi==%" PRIu32
79 ", AHardwareBuffer_Format==%" PRIu32 ".",
80 static_cast<int>(context->backend()), desc.format);
Nolan Scobie2163e412022-10-24 19:57:43 -040081 LOG_ALWAYS_FATAL_IF(!mBackendTexture.isValid(),
82 __FILE__ " Invalid GrBackendTexture. Width==%" PRIu32 ", height==%" PRIu32
83 ", protected==%d",
84 desc.width, desc.height, createProtectedImage);
Stan Ilievaaa9e832019-09-17 14:07:23 -040085}
86
87void AutoBackendTextureRelease::unref(bool releaseImage) {
88 if (!RenderThread::isCurrent()) {
89 // EGLImage needs to be destroyed on RenderThread to prevent memory leak.
90 // ~SkImage dtor for both pipelines needs to be invoked on RenderThread, because it is not
91 // thread safe.
92 RenderThread::getInstance().queue().post([this, releaseImage]() { unref(releaseImage); });
93 return;
94 }
95
96 if (releaseImage) {
97 mImage.reset();
98 }
99
100 mUsageCount--;
101 if (mUsageCount <= 0) {
102 if (mBackendTexture.isValid()) {
103 mDeleteProc(mImageCtx);
104 mBackendTexture = {};
105 }
106 delete this;
107 }
108}
109
110// releaseProc is invoked by SkImage, when texture is no longer in use.
111// "releaseContext" contains an "AutoBackendTextureRelease*".
Kevin Lubick36e81af2023-05-11 14:58:45 +0000112static void releaseProc(SkImages::ReleaseContext releaseContext) {
Stan Ilievaaa9e832019-09-17 14:07:23 -0400113 AutoBackendTextureRelease* textureRelease =
114 reinterpret_cast<AutoBackendTextureRelease*>(releaseContext);
115 textureRelease->unref(false);
116}
117
Adlai Hollerf8c434e2020-07-27 11:42:45 -0400118void AutoBackendTextureRelease::makeImage(AHardwareBuffer* buffer,
119 android_dataspace dataspace,
120 GrDirectContext* context) {
Stan Ilievaaa9e832019-09-17 14:07:23 -0400121 AHardwareBuffer_Desc desc;
122 AHardwareBuffer_describe(buffer, &desc);
123 SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format);
Nolan Scobie2163e412022-10-24 19:57:43 -0400124 // The following ref will be counteracted by Skia calling releaseProc, either during
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +0000125 // BorrowTextureFrom if there is a failure, or later when SkImage is discarded. It must
126 // be called before BorrowTextureFrom, otherwise Skia may remove HWUI's ref on failure.
Nolan Scobie2163e412022-10-24 19:57:43 -0400127 ref();
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +0000128 mImage = SkImages::BorrowTextureFrom(
Stan Ilievaaa9e832019-09-17 14:07:23 -0400129 context, mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType,
130 uirenderer::DataSpaceToColorSpace(dataspace), releaseProc, this);
Stan Ilievaaa9e832019-09-17 14:07:23 -0400131}
132
Adlai Hollerf8c434e2020-07-27 11:42:45 -0400133void AutoBackendTextureRelease::newBufferContent(GrDirectContext* context) {
Stan Ilievaaa9e832019-09-17 14:07:23 -0400134 if (mBackendTexture.isValid()) {
135 mUpdateProc(mImageCtx, context);
136 }
137}
138
Greg Daniel27e1fa22021-05-26 09:24:15 -0400139void AutoBackendTextureRelease::releaseQueueOwnership(GrDirectContext* context) {
140 if (!context) {
141 return;
142 }
143
Penghui.Liu255ee522024-08-26 20:43:49 +0800144 if (!RenderThread::isCurrent()) {
145 // releaseQueueOwnership needs to run on RenderThread to prevent multithread calling
146 // setBackendTextureState will operate skia resource cache which need single owner
147 RenderThread::getInstance().queue().post([this, context]() { releaseQueueOwnership(context); });
148 return;
149 }
150
Greg Daniel27e1fa22021-05-26 09:24:15 -0400151 LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan);
152 if (mBackendTexture.isValid()) {
153 // Passing in VK_IMAGE_LAYOUT_UNDEFINED means we keep the old layout.
Kevin Lubick41403bd2024-01-22 17:28:40 +0000154 skgpu::MutableTextureState newState = skgpu::MutableTextureStates::MakeVulkan(
155 VK_IMAGE_LAYOUT_UNDEFINED,
156 VK_QUEUE_FAMILY_FOREIGN_EXT);
Greg Daniel27e1fa22021-05-26 09:24:15 -0400157
158 // The unref for this ref happens in the releaseProc passed into setBackendTextureState. The
159 // releaseProc callback will be made when the work to set the new state has finished on the
160 // gpu.
161 ref();
162 // Note that we don't have an explicit call to set the backend texture back onto the
163 // graphics queue when we use the VkImage again. Internally, Skia will notice that the image
164 // is not on the graphics queue and will do the transition automatically.
165 context->setBackendTextureState(mBackendTexture, newState, nullptr, releaseProc, this);
166 }
167}
168
Stan Ilievaaa9e832019-09-17 14:07:23 -0400169} /* namespace uirenderer */
170} /* namespace android */