blob: 16de21def0e3973ecd1c833108e010cdf9faf848 [file] [log] [blame]
John Recke170fb62018-05-07 08:12:07 -07001/*
2 * Copyright (C) 2018 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 "HardwareBitmapUploader.h"
18
Alec Mouri45238012020-01-29 11:04:40 -080019#include <EGL/egl.h>
John Recke170fb62018-05-07 08:12:07 -070020#include <EGL/eglext.h>
21#include <GLES2/gl2.h>
22#include <GLES2/gl2ext.h>
23#include <GLES3/gl3.h>
Adlai Hollerf8c434e2020-07-27 11:42:45 -040024#include <GrDirectContext.h>
Kevin Lubickcae0b212023-09-12 18:33:10 +000025#include <GrTypes.h>
Kevin Lubick1175dc02022-02-28 12:41:27 -050026#include <SkBitmap.h>
John Recke170fb62018-05-07 08:12:07 -070027#include <SkCanvas.h>
Greg Danielc0732522019-02-20 08:31:03 -050028#include <SkImage.h>
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +000029#include <SkImageAndroid.h>
Kevin Lubick1175dc02022-02-28 12:41:27 -050030#include <SkImageInfo.h>
31#include <SkRefCnt.h>
rnleece9762b2021-05-21 15:40:53 -070032#include <gui/TraceUtils.h>
John Recke170fb62018-05-07 08:12:07 -070033#include <utils/GLUtils.h>
Alec Mouri45238012020-01-29 11:04:40 -080034#include <utils/NdkUtils.h>
John Recke170fb62018-05-07 08:12:07 -070035#include <utils/Trace.h>
Alec Mouri45238012020-01-29 11:04:40 -080036
John Recke170fb62018-05-07 08:12:07 -070037#include <thread>
38
Alec Mouri45238012020-01-29 11:04:40 -080039#include "hwui/Bitmap.h"
40#include "renderthread/EglManager.h"
41#include "renderthread/VulkanManager.h"
42#include "thread/ThreadBase.h"
43#include "utils/TimeUtils.h"
44
John Recke170fb62018-05-07 08:12:07 -070045namespace android::uirenderer {
46
John Reck5f66fb82022-09-23 17:49:23 -040047static constexpr auto kThreadTimeout = 60000_ms;
48
Greg Danielc0732522019-02-20 08:31:03 -050049class AHBUploader;
50// This helper uploader classes allows us to upload using either EGL or Vulkan using the same
51// interface.
52static sp<AHBUploader> sUploader = nullptr;
John Recke170fb62018-05-07 08:12:07 -070053
Greg Danielc0732522019-02-20 08:31:03 -050054struct FormatInfo {
Alec Mouri45238012020-01-29 11:04:40 -080055 AHardwareBuffer_Format bufferFormat;
Greg Danielc0732522019-02-20 08:31:03 -050056 GLint format, type;
57 VkFormat vkFormat;
58 bool isSupported = false;
59 bool valid = true;
60};
John Recke170fb62018-05-07 08:12:07 -070061
Greg Danielc0732522019-02-20 08:31:03 -050062class AHBUploader : public RefBase {
63public:
64 virtual ~AHBUploader() {}
John Recke170fb62018-05-07 08:12:07 -070065
Greg Danielc0732522019-02-20 08:31:03 -050066 void destroy() {
67 std::lock_guard _lock{mLock};
68 LOG_ALWAYS_FATAL_IF(mPendingUploads, "terminate called while uploads in progress");
69 if (mUploadThread) {
70 mUploadThread->requestExit();
71 mUploadThread->join();
72 mUploadThread = nullptr;
73 }
74 onDestroy();
John Recke170fb62018-05-07 08:12:07 -070075 }
76
Greg Danielc0732522019-02-20 08:31:03 -050077 bool uploadHardwareBitmap(const SkBitmap& bitmap, const FormatInfo& format,
Alec Mouri45238012020-01-29 11:04:40 -080078 AHardwareBuffer* ahb) {
Greg Danielc0732522019-02-20 08:31:03 -050079 ATRACE_CALL();
80 beginUpload();
Alec Mouri45238012020-01-29 11:04:40 -080081 bool result = onUploadHardwareBitmap(bitmap, format, ahb);
Greg Danielc0732522019-02-20 08:31:03 -050082 endUpload();
83 return result;
84 }
85
86 void postIdleTimeoutCheck() {
John Reck5f66fb82022-09-23 17:49:23 -040087 mUploadThread->queue().postDelayed(kThreadTimeout, [this]() { this->idleTimeoutCheck(); });
Greg Danielc0732522019-02-20 08:31:03 -050088 }
89
90protected:
91 std::mutex mLock;
92 sp<ThreadBase> mUploadThread = nullptr;
93
94private:
Greg Danielc0732522019-02-20 08:31:03 -050095 virtual void onIdle() = 0;
96 virtual void onDestroy() = 0;
97
98 virtual bool onUploadHardwareBitmap(const SkBitmap& bitmap, const FormatInfo& format,
Alec Mouri45238012020-01-29 11:04:40 -080099 AHardwareBuffer* ahb) = 0;
Greg Danielc0732522019-02-20 08:31:03 -0500100 virtual void onBeginUpload() = 0;
101
102 bool shouldTimeOutLocked() {
103 nsecs_t durationSince = systemTime() - mLastUpload;
John Reck5f66fb82022-09-23 17:49:23 -0400104 return durationSince > kThreadTimeout;
Greg Danielc0732522019-02-20 08:31:03 -0500105 }
106
107 void idleTimeoutCheck() {
108 std::lock_guard _lock{mLock};
109 if (mPendingUploads == 0 && shouldTimeOutLocked()) {
110 onIdle();
111 } else {
112 this->postIdleTimeoutCheck();
113 }
114 }
115
116 void beginUpload() {
117 std::lock_guard _lock{mLock};
118 mPendingUploads++;
119
120 if (!mUploadThread) {
121 mUploadThread = new ThreadBase{};
122 }
123 if (!mUploadThread->isRunning()) {
124 mUploadThread->start("GrallocUploadThread");
125 }
126
127 onBeginUpload();
128 }
129
130 void endUpload() {
131 std::lock_guard _lock{mLock};
132 mPendingUploads--;
133 mLastUpload = systemTime();
134 }
135
136 int mPendingUploads = 0;
137 nsecs_t mLastUpload = 0;
138};
139
140#define FENCE_TIMEOUT 2000000000
141
142class EGLUploader : public AHBUploader {
143private:
Greg Danielc0732522019-02-20 08:31:03 -0500144 void onDestroy() override {
145 mEglManager.destroy();
146 }
147 void onIdle() override {
148 mEglManager.destroy();
149 }
150
151 void onBeginUpload() override {
152 if (!mEglManager.hasEglContext()) {
153 mUploadThread->queue().runSync([this]() {
154 this->mEglManager.initialize();
155 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
156 });
157
158 this->postIdleTimeoutCheck();
159 }
160 }
161
162
163 EGLDisplay getUploadEglDisplay() {
164 std::lock_guard _lock{mLock};
165 LOG_ALWAYS_FATAL_IF(!mEglManager.hasEglContext(), "Forgot to begin an upload?");
166 return mEglManager.eglDisplay();
167 }
168
169 bool onUploadHardwareBitmap(const SkBitmap& bitmap, const FormatInfo& format,
Alec Mouri45238012020-01-29 11:04:40 -0800170 AHardwareBuffer* ahb) override {
Greg Danielc0732522019-02-20 08:31:03 -0500171 ATRACE_CALL();
172
173 EGLDisplay display = getUploadEglDisplay();
174
175 LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
176 uirenderer::renderthread::EglManager::eglErrorString());
Alec Mouri45238012020-01-29 11:04:40 -0800177 // We use an EGLImage to access the content of the buffer
Greg Danielc0732522019-02-20 08:31:03 -0500178 // The EGL image is later bound to a 2D texture
Alec Mouri70463a62020-03-30 15:10:17 -0700179 const EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(ahb);
Greg Danielc0732522019-02-20 08:31:03 -0500180 AutoEglImage autoImage(display, clientBuffer);
181 if (autoImage.image == EGL_NO_IMAGE_KHR) {
182 ALOGW("Could not create EGL image, err =%s",
183 uirenderer::renderthread::EglManager::eglErrorString());
184 return false;
185 }
186
187 {
188 ATRACE_FORMAT("CPU -> gralloc transfer (%dx%d)", bitmap.width(), bitmap.height());
189 EGLSyncKHR fence = mUploadThread->queue().runSync([&]() -> EGLSyncKHR {
190 AutoSkiaGlTexture glTexture;
191 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image);
John Reck996773a2020-02-03 16:30:56 -0800192 if (GLUtils::dumpGLErrors()) {
193 return EGL_NO_SYNC_KHR;
194 }
Greg Danielc0732522019-02-20 08:31:03 -0500195
196 // glTexSubImage2D is synchronous in sense that it memcpy() from pointer that we
197 // provide.
198 // But asynchronous in sense that driver may upload texture onto hardware buffer
199 // when we first use it in drawing
200 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
201 format.format, format.type, bitmap.getPixels());
John Reck996773a2020-02-03 16:30:56 -0800202 if (GLUtils::dumpGLErrors()) {
203 return EGL_NO_SYNC_KHR;
204 }
Greg Danielc0732522019-02-20 08:31:03 -0500205
206 EGLSyncKHR uploadFence =
207 eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_FENCE_KHR, NULL);
John Reck996773a2020-02-03 16:30:56 -0800208 if (uploadFence == EGL_NO_SYNC_KHR) {
209 ALOGW("Could not create sync fence %#x", eglGetError());
210 };
Greg Danielc0732522019-02-20 08:31:03 -0500211 glFlush();
John Reck996773a2020-02-03 16:30:56 -0800212 GLUtils::dumpGLErrors();
Greg Danielc0732522019-02-20 08:31:03 -0500213 return uploadFence;
214 });
215
John Reck996773a2020-02-03 16:30:56 -0800216 if (fence == EGL_NO_SYNC_KHR) {
217 return false;
218 }
Greg Danielc0732522019-02-20 08:31:03 -0500219 EGLint waitStatus = eglClientWaitSyncKHR(display, fence, 0, FENCE_TIMEOUT);
John Reck996773a2020-02-03 16:30:56 -0800220 ALOGE_IF(waitStatus != EGL_CONDITION_SATISFIED_KHR,
221 "Failed to wait for the fence %#x", eglGetError());
Greg Danielc0732522019-02-20 08:31:03 -0500222
223 eglDestroySyncKHR(display, fence);
224 }
225 return true;
226 }
227
228 renderthread::EglManager mEglManager;
229};
230
231class VkUploader : public AHBUploader {
232private:
Greg Danielc0732522019-02-20 08:31:03 -0500233 void onDestroy() override {
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400234 std::lock_guard _lock{mVkLock};
Greg Danielc0732522019-02-20 08:31:03 -0500235 mGrContext.reset();
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400236 mVulkanManagerStrong.clear();
Greg Danielc0732522019-02-20 08:31:03 -0500237 }
238 void onIdle() override {
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400239 onDestroy();
Greg Danielc0732522019-02-20 08:31:03 -0500240 }
John Recke170fb62018-05-07 08:12:07 -0700241
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400242 void onBeginUpload() override {}
John Recke170fb62018-05-07 08:12:07 -0700243
Greg Danielc0732522019-02-20 08:31:03 -0500244 bool onUploadHardwareBitmap(const SkBitmap& bitmap, const FormatInfo& format,
Alec Mouri45238012020-01-29 11:04:40 -0800245 AHardwareBuffer* ahb) override {
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400246 bool uploadSucceeded = false;
247 mUploadThread->queue().runSync([this, &uploadSucceeded, bitmap, ahb]() {
248 ATRACE_CALL();
249 std::lock_guard _lock{mVkLock};
Greg Danielc0732522019-02-20 08:31:03 -0500250
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400251 renderthread::VulkanManager* vkManager = getVulkanManager();
252 if (!vkManager->hasVkContext()) {
253 LOG_ALWAYS_FATAL_IF(mGrContext,
254 "GrContext exists with no VulkanManager for vulkan uploads");
255 vkManager->initialize();
256 }
Greg Danielc0732522019-02-20 08:31:03 -0500257
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400258 if (!mGrContext) {
259 GrContextOptions options;
260 mGrContext = vkManager->createContext(options,
261 renderthread::VulkanManager::ContextType::kUploadThread);
262 LOG_ALWAYS_FATAL_IF(!mGrContext, "failed to create GrContext for vulkan uploads");
263 this->postIdleTimeoutCheck();
264 }
265
266 sk_sp<SkImage> image =
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +0000267 SkImages::TextureFromAHardwareBufferWithData(mGrContext.get(), bitmap.pixmap(),
268 ahb);
Kevin Lubickcae0b212023-09-12 18:33:10 +0000269 mGrContext->submit(GrSyncCpu::kYes);
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400270
271 uploadSucceeded = (image.get() != nullptr);
272 });
273 return uploadSucceeded;
274 }
275
276 /* must be called on the upload thread after the vkLock has been acquired */
277 renderthread::VulkanManager* getVulkanManager() {
278 if (!mVulkanManagerStrong) {
279 mVulkanManagerStrong = mVulkanManagerWeak.promote();
280
281 // create a new manager if we couldn't promote the weak ref
282 if (!mVulkanManagerStrong) {
283 mVulkanManagerStrong = renderthread::VulkanManager::getInstance();
284 mGrContext.reset();
285 mVulkanManagerWeak = mVulkanManagerStrong;
286 }
287 }
288
289 return mVulkanManagerStrong.get();
Greg Danielc0732522019-02-20 08:31:03 -0500290 }
291
Adlai Hollerf8c434e2020-07-27 11:42:45 -0400292 sk_sp<GrDirectContext> mGrContext;
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400293 sp<renderthread::VulkanManager> mVulkanManagerStrong;
294 wp<renderthread::VulkanManager> mVulkanManagerWeak;
Greg Danielc0732522019-02-20 08:31:03 -0500295 std::mutex mVkLock;
296};
John Recke170fb62018-05-07 08:12:07 -0700297
Alec Mouri1efd0a52022-01-20 13:58:23 -0800298static bool checkSupport(AHardwareBuffer_Format format) {
299 AHardwareBuffer_Desc desc = {
300 .width = 1,
301 .height = 1,
302 .layers = 1,
303 .format = format,
304 .usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
305 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
306 };
307 UniqueAHardwareBuffer buffer = allocateAHardwareBuffer(desc);
308 return buffer != nullptr;
309}
310
Leon Scroggins IIIee3bfe72019-01-31 08:42:23 -0500311bool HardwareBitmapUploader::hasFP16Support() {
Alec Mouri1efd0a52022-01-20 13:58:23 -0800312 static bool hasFP16Support = checkSupport(AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT);
John Recke170fb62018-05-07 08:12:07 -0700313 return hasFP16Support;
314}
315
Alec Mouri1efd0a52022-01-20 13:58:23 -0800316bool HardwareBitmapUploader::has1010102Support() {
317 static bool has101012Support = checkSupport(AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM);
318 return has101012Support;
319}
320
Leon Scroggins IIIa008aa92022-03-10 16:25:30 -0500321bool HardwareBitmapUploader::hasAlpha8Support() {
322 static bool hasAlpha8Support = checkSupport(AHARDWAREBUFFER_FORMAT_R8_UNORM);
323 return hasAlpha8Support;
324}
325
Greg Danielc0732522019-02-20 08:31:03 -0500326static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) {
John Recke170fb62018-05-07 08:12:07 -0700327 FormatInfo formatInfo;
John Recke170fb62018-05-07 08:12:07 -0700328 switch (skBitmap.info().colorType()) {
329 case kRGBA_8888_SkColorType:
330 formatInfo.isSupported = true;
Colin Crossf4e74b82019-10-31 13:47:42 -0700331 [[fallthrough]];
John Recke170fb62018-05-07 08:12:07 -0700332 // ARGB_4444 is upconverted to RGBA_8888
333 case kARGB_4444_SkColorType:
Alec Mouri45238012020-01-29 11:04:40 -0800334 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700335 formatInfo.format = GL_RGBA;
336 formatInfo.type = GL_UNSIGNED_BYTE;
Greg Danielc0732522019-02-20 08:31:03 -0500337 formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700338 break;
339 case kRGBA_F16_SkColorType:
Leon Scroggins IIIee3bfe72019-01-31 08:42:23 -0500340 formatInfo.isSupported = HardwareBitmapUploader::hasFP16Support();
John Recke170fb62018-05-07 08:12:07 -0700341 if (formatInfo.isSupported) {
342 formatInfo.type = GL_HALF_FLOAT;
Alec Mouri45238012020-01-29 11:04:40 -0800343 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
Greg Danielc0732522019-02-20 08:31:03 -0500344 formatInfo.vkFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
John Recke170fb62018-05-07 08:12:07 -0700345 } else {
346 formatInfo.type = GL_UNSIGNED_BYTE;
Alec Mouri45238012020-01-29 11:04:40 -0800347 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
Greg Danielc0732522019-02-20 08:31:03 -0500348 formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700349 }
350 formatInfo.format = GL_RGBA;
351 break;
352 case kRGB_565_SkColorType:
353 formatInfo.isSupported = true;
Alec Mouri45238012020-01-29 11:04:40 -0800354 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700355 formatInfo.format = GL_RGB;
356 formatInfo.type = GL_UNSIGNED_SHORT_5_6_5;
Greg Danielc0732522019-02-20 08:31:03 -0500357 formatInfo.vkFormat = VK_FORMAT_R5G6B5_UNORM_PACK16;
John Recke170fb62018-05-07 08:12:07 -0700358 break;
359 case kGray_8_SkColorType:
Greg Danielc0732522019-02-20 08:31:03 -0500360 formatInfo.isSupported = usingGL;
Alec Mouri45238012020-01-29 11:04:40 -0800361 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700362 formatInfo.format = GL_LUMINANCE;
363 formatInfo.type = GL_UNSIGNED_BYTE;
Greg Danielc0732522019-02-20 08:31:03 -0500364 formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700365 break;
Alec Mouri1efd0a52022-01-20 13:58:23 -0800366 case kRGBA_1010102_SkColorType:
367 formatInfo.isSupported = HardwareBitmapUploader::has1010102Support();
368 if (formatInfo.isSupported) {
369 formatInfo.type = GL_UNSIGNED_INT_2_10_10_10_REV;
370 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
371 formatInfo.vkFormat = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
372 } else {
373 formatInfo.type = GL_UNSIGNED_BYTE;
374 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
375 formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
376 }
377 formatInfo.format = GL_RGBA;
378 break;
Leon Scroggins IIIa008aa92022-03-10 16:25:30 -0500379 case kAlpha_8_SkColorType:
380 formatInfo.isSupported = HardwareBitmapUploader::hasAlpha8Support();
381 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8_UNORM;
382 formatInfo.format = GL_R8;
383 formatInfo.type = GL_UNSIGNED_BYTE;
384 formatInfo.vkFormat = VK_FORMAT_R8_UNORM;
385 break;
John Recke170fb62018-05-07 08:12:07 -0700386 default:
387 ALOGW("unable to create hardware bitmap of colortype: %d", skBitmap.info().colorType());
388 formatInfo.valid = false;
389 }
390 return formatInfo;
391}
392
393static SkBitmap makeHwCompatible(const FormatInfo& format, const SkBitmap& source) {
394 if (format.isSupported) {
395 return source;
396 } else {
397 SkBitmap bitmap;
Mike Reed7994a312021-01-28 18:06:26 -0500398 bitmap.allocPixels(source.info().makeColorType(kN32_SkColorType));
399 bitmap.writePixels(source.pixmap());
John Recke170fb62018-05-07 08:12:07 -0700400 return bitmap;
401 }
402}
403
Greg Danielc0732522019-02-20 08:31:03 -0500404
405static void createUploader(bool usingGL) {
406 static std::mutex lock;
407 std::lock_guard _lock{lock};
408 if (!sUploader.get()) {
409 if (usingGL) {
410 sUploader = new EGLUploader();
411 } else {
412 sUploader = new VkUploader();
413 }
414 }
415}
John Recke170fb62018-05-07 08:12:07 -0700416
417sk_sp<Bitmap> HardwareBitmapUploader::allocateHardwareBitmap(const SkBitmap& sourceBitmap) {
418 ATRACE_CALL();
419
Greg Danielc0732522019-02-20 08:31:03 -0500420 bool usingGL = uirenderer::Properties::getRenderPipelineType() ==
421 uirenderer::RenderPipelineType::SkiaGL;
422
423 FormatInfo format = determineFormat(sourceBitmap, usingGL);
John Recke170fb62018-05-07 08:12:07 -0700424 if (!format.valid) {
425 return nullptr;
426 }
427
John Recke170fb62018-05-07 08:12:07 -0700428 SkBitmap bitmap = makeHwCompatible(format, sourceBitmap);
Alec Mouri45238012020-01-29 11:04:40 -0800429 AHardwareBuffer_Desc desc = {
430 .width = static_cast<uint32_t>(bitmap.width()),
431 .height = static_cast<uint32_t>(bitmap.height()),
432 .layers = 1,
433 .format = format.bufferFormat,
434 .usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
435 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
436 };
437 UniqueAHardwareBuffer ahb = allocateAHardwareBuffer(desc);
438 if (!ahb) {
439 ALOGW("allocateHardwareBitmap() failed in AHardwareBuffer_allocate()");
John Recke170fb62018-05-07 08:12:07 -0700440 return nullptr;
Alec Mouri45238012020-01-29 11:04:40 -0800441 };
John Recke170fb62018-05-07 08:12:07 -0700442
Greg Danielc0732522019-02-20 08:31:03 -0500443 createUploader(usingGL);
John Recke170fb62018-05-07 08:12:07 -0700444
Alec Mouri45238012020-01-29 11:04:40 -0800445 if (!sUploader->uploadHardwareBitmap(bitmap, format, ahb.get())) {
John Recke170fb62018-05-07 08:12:07 -0700446 return nullptr;
447 }
Alec Mouri45238012020-01-29 11:04:40 -0800448 return Bitmap::createFrom(ahb.get(), bitmap.colorType(), bitmap.refColorSpace(),
449 bitmap.alphaType(), Bitmap::computePalette(bitmap));
John Recke170fb62018-05-07 08:12:07 -0700450}
451
Greg Danielc0732522019-02-20 08:31:03 -0500452void HardwareBitmapUploader::initialize() {
453 bool usingGL = uirenderer::Properties::getRenderPipelineType() ==
454 uirenderer::RenderPipelineType::SkiaGL;
455 createUploader(usingGL);
Greg Danielc0732522019-02-20 08:31:03 -0500456}
457
John Reck6104cea2019-01-10 14:37:17 -0800458void HardwareBitmapUploader::terminate() {
Greg Daniel78b7ddc2019-03-27 12:52:43 -0400459 if (sUploader) {
460 sUploader->destroy();
461 }
John Reck6104cea2019-01-10 14:37:17 -0800462}
463
Chris Blume7b8a8082018-11-30 15:51:58 -0800464} // namespace android::uirenderer