blob: fcb1bfeae6b54cf40824a8275068723d6cfe77c0 [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>
Kevin Lubickb5ad05c2023-06-05 17:34:05 +000021#include <include/gpu/GrBackendSurfaceMutableState.h>
22#include <include/gpu/GrDirectContext.h>
23#include <include/gpu/GrBackendSurface.h>
Stan Ilievaaa9e832019-09-17 14:07:23 -040024#include "renderthread/RenderThread.h"
25#include "utils/Color.h"
26#include "utils/PaintUtils.h"
27
28using namespace android::uirenderer::renderthread;
29
30namespace android {
31namespace uirenderer {
32
Adlai Hollerf8c434e2020-07-27 11:42:45 -040033AutoBackendTextureRelease::AutoBackendTextureRelease(GrDirectContext* context,
34 AHardwareBuffer* buffer) {
Stan Ilievaaa9e832019-09-17 14:07:23 -040035 AHardwareBuffer_Desc desc;
36 AHardwareBuffer_describe(buffer, &desc);
37 bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
Kevin Lubick60d06862023-08-07 15:29:12 +000038
39 GrBackendFormat backendFormat;
40 GrBackendApi backend = context->backend();
41 if (backend == GrBackendApi::kOpenGL) {
42 backendFormat =
43 GrAHardwareBufferUtils::GetGLBackendFormat(context, desc.format, false);
44 mBackendTexture =
45 GrAHardwareBufferUtils::MakeGLBackendTexture(context,
46 buffer,
47 desc.width,
48 desc.height,
49 &mDeleteProc,
50 &mUpdateProc,
51 &mImageCtx,
52 createProtectedImage,
53 backendFormat,
54 false);
55 } else if (backend == GrBackendApi::kVulkan) {
56 backendFormat =
57 GrAHardwareBufferUtils::GetVulkanBackendFormat(context,
58 buffer,
59 desc.format,
60 false);
61 mBackendTexture =
62 GrAHardwareBufferUtils::MakeVulkanBackendTexture(context,
63 buffer,
64 desc.width,
65 desc.height,
66 &mDeleteProc,
67 &mUpdateProc,
68 &mImageCtx,
69 createProtectedImage,
70 backendFormat,
71 false);
72 } else {
73 LOG_ALWAYS_FATAL("Unexpected backend %d", backend);
74 }
Nolan Scobie2163e412022-10-24 19:57:43 -040075 LOG_ALWAYS_FATAL_IF(!backendFormat.isValid(),
76 __FILE__ " Invalid GrBackendFormat. GrBackendApi==%" PRIu32
77 ", AHardwareBuffer_Format==%" PRIu32 ".",
78 static_cast<int>(context->backend()), desc.format);
Nolan Scobie2163e412022-10-24 19:57:43 -040079 LOG_ALWAYS_FATAL_IF(!mBackendTexture.isValid(),
80 __FILE__ " Invalid GrBackendTexture. Width==%" PRIu32 ", height==%" PRIu32
81 ", protected==%d",
82 desc.width, desc.height, createProtectedImage);
Stan Ilievaaa9e832019-09-17 14:07:23 -040083}
84
85void AutoBackendTextureRelease::unref(bool releaseImage) {
86 if (!RenderThread::isCurrent()) {
87 // EGLImage needs to be destroyed on RenderThread to prevent memory leak.
88 // ~SkImage dtor for both pipelines needs to be invoked on RenderThread, because it is not
89 // thread safe.
90 RenderThread::getInstance().queue().post([this, releaseImage]() { unref(releaseImage); });
91 return;
92 }
93
94 if (releaseImage) {
95 mImage.reset();
96 }
97
98 mUsageCount--;
99 if (mUsageCount <= 0) {
100 if (mBackendTexture.isValid()) {
101 mDeleteProc(mImageCtx);
102 mBackendTexture = {};
103 }
104 delete this;
105 }
106}
107
108// releaseProc is invoked by SkImage, when texture is no longer in use.
109// "releaseContext" contains an "AutoBackendTextureRelease*".
Kevin Lubick36e81af2023-05-11 14:58:45 +0000110static void releaseProc(SkImages::ReleaseContext releaseContext) {
Stan Ilievaaa9e832019-09-17 14:07:23 -0400111 AutoBackendTextureRelease* textureRelease =
112 reinterpret_cast<AutoBackendTextureRelease*>(releaseContext);
113 textureRelease->unref(false);
114}
115
Adlai Hollerf8c434e2020-07-27 11:42:45 -0400116void AutoBackendTextureRelease::makeImage(AHardwareBuffer* buffer,
117 android_dataspace dataspace,
118 GrDirectContext* context) {
Stan Ilievaaa9e832019-09-17 14:07:23 -0400119 AHardwareBuffer_Desc desc;
120 AHardwareBuffer_describe(buffer, &desc);
121 SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format);
Nolan Scobie2163e412022-10-24 19:57:43 -0400122 // The following ref will be counteracted by Skia calling releaseProc, either during
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +0000123 // BorrowTextureFrom if there is a failure, or later when SkImage is discarded. It must
124 // be called before BorrowTextureFrom, otherwise Skia may remove HWUI's ref on failure.
Nolan Scobie2163e412022-10-24 19:57:43 -0400125 ref();
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +0000126 mImage = SkImages::BorrowTextureFrom(
Stan Ilievaaa9e832019-09-17 14:07:23 -0400127 context, mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType,
128 uirenderer::DataSpaceToColorSpace(dataspace), releaseProc, this);
Stan Ilievaaa9e832019-09-17 14:07:23 -0400129}
130
Adlai Hollerf8c434e2020-07-27 11:42:45 -0400131void AutoBackendTextureRelease::newBufferContent(GrDirectContext* context) {
Stan Ilievaaa9e832019-09-17 14:07:23 -0400132 if (mBackendTexture.isValid()) {
133 mUpdateProc(mImageCtx, context);
134 }
135}
136
Greg Daniel27e1fa22021-05-26 09:24:15 -0400137void AutoBackendTextureRelease::releaseQueueOwnership(GrDirectContext* context) {
138 if (!context) {
139 return;
140 }
141
142 LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan);
143 if (mBackendTexture.isValid()) {
144 // Passing in VK_IMAGE_LAYOUT_UNDEFINED means we keep the old layout.
145 GrBackendSurfaceMutableState newState(VK_IMAGE_LAYOUT_UNDEFINED,
146 VK_QUEUE_FAMILY_FOREIGN_EXT);
147
148 // The unref for this ref happens in the releaseProc passed into setBackendTextureState. The
149 // releaseProc callback will be made when the work to set the new state has finished on the
150 // gpu.
151 ref();
152 // Note that we don't have an explicit call to set the backend texture back onto the
153 // graphics queue when we use the VkImage again. Internally, Skia will notice that the image
154 // is not on the graphics queue and will do the transition automatically.
155 context->setBackendTextureState(mBackendTexture, newState, nullptr, releaseProc, this);
156 }
157}
158
Stan Ilievaaa9e832019-09-17 14:07:23 -0400159} /* namespace uirenderer */
160} /* namespace android */