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