blob: 19a1dfa9153985027b836870475cbd118f077ad8 [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 Lubick1175dc02022-02-28 12:41:27 -050025#include <SkBitmap.h>
John Recke170fb62018-05-07 08:12:07 -070026#include <SkCanvas.h>
Greg Danielc0732522019-02-20 08:31:03 -050027#include <SkImage.h>
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +000028#include <SkImageAndroid.h>
Kevin Lubick1175dc02022-02-28 12:41:27 -050029#include <SkImageInfo.h>
30#include <SkRefCnt.h>
rnleece9762b2021-05-21 15:40:53 -070031#include <gui/TraceUtils.h>
John Recke170fb62018-05-07 08:12:07 -070032#include <utils/GLUtils.h>
Alec Mouri45238012020-01-29 11:04:40 -080033#include <utils/NdkUtils.h>
John Recke170fb62018-05-07 08:12:07 -070034#include <utils/Trace.h>
Alec Mouri45238012020-01-29 11:04:40 -080035
John Recke170fb62018-05-07 08:12:07 -070036#include <thread>
37
Alec Mouri45238012020-01-29 11:04:40 -080038#include "hwui/Bitmap.h"
39#include "renderthread/EglManager.h"
40#include "renderthread/VulkanManager.h"
41#include "thread/ThreadBase.h"
42#include "utils/TimeUtils.h"
43
John Recke170fb62018-05-07 08:12:07 -070044namespace android::uirenderer {
45
John Reck5f66fb82022-09-23 17:49:23 -040046static constexpr auto kThreadTimeout = 60000_ms;
47
Greg Danielc0732522019-02-20 08:31:03 -050048class AHBUploader;
49// This helper uploader classes allows us to upload using either EGL or Vulkan using the same
50// interface.
51static sp<AHBUploader> sUploader = nullptr;
John Recke170fb62018-05-07 08:12:07 -070052
Greg Danielc0732522019-02-20 08:31:03 -050053struct FormatInfo {
Alec Mouri45238012020-01-29 11:04:40 -080054 AHardwareBuffer_Format bufferFormat;
Greg Danielc0732522019-02-20 08:31:03 -050055 GLint format, type;
56 VkFormat vkFormat;
57 bool isSupported = false;
58 bool valid = true;
59};
John Recke170fb62018-05-07 08:12:07 -070060
Greg Danielc0732522019-02-20 08:31:03 -050061class AHBUploader : public RefBase {
62public:
63 virtual ~AHBUploader() {}
John Recke170fb62018-05-07 08:12:07 -070064
Greg Danielc0732522019-02-20 08:31:03 -050065 void destroy() {
66 std::lock_guard _lock{mLock};
67 LOG_ALWAYS_FATAL_IF(mPendingUploads, "terminate called while uploads in progress");
68 if (mUploadThread) {
69 mUploadThread->requestExit();
70 mUploadThread->join();
71 mUploadThread = nullptr;
72 }
73 onDestroy();
John Recke170fb62018-05-07 08:12:07 -070074 }
75
Greg Danielc0732522019-02-20 08:31:03 -050076 bool uploadHardwareBitmap(const SkBitmap& bitmap, const FormatInfo& format,
Alec Mouri45238012020-01-29 11:04:40 -080077 AHardwareBuffer* ahb) {
Greg Danielc0732522019-02-20 08:31:03 -050078 ATRACE_CALL();
79 beginUpload();
Alec Mouri45238012020-01-29 11:04:40 -080080 bool result = onUploadHardwareBitmap(bitmap, format, ahb);
Greg Danielc0732522019-02-20 08:31:03 -050081 endUpload();
82 return result;
83 }
84
85 void postIdleTimeoutCheck() {
John Reck5f66fb82022-09-23 17:49:23 -040086 mUploadThread->queue().postDelayed(kThreadTimeout, [this]() { this->idleTimeoutCheck(); });
Greg Danielc0732522019-02-20 08:31:03 -050087 }
88
89protected:
90 std::mutex mLock;
91 sp<ThreadBase> mUploadThread = nullptr;
92
93private:
Greg Danielc0732522019-02-20 08:31:03 -050094 virtual void onIdle() = 0;
95 virtual void onDestroy() = 0;
96
97 virtual bool onUploadHardwareBitmap(const SkBitmap& bitmap, const FormatInfo& format,
Alec Mouri45238012020-01-29 11:04:40 -080098 AHardwareBuffer* ahb) = 0;
Greg Danielc0732522019-02-20 08:31:03 -050099 virtual void onBeginUpload() = 0;
100
101 bool shouldTimeOutLocked() {
102 nsecs_t durationSince = systemTime() - mLastUpload;
John Reck5f66fb82022-09-23 17:49:23 -0400103 return durationSince > kThreadTimeout;
Greg Danielc0732522019-02-20 08:31:03 -0500104 }
105
106 void idleTimeoutCheck() {
107 std::lock_guard _lock{mLock};
108 if (mPendingUploads == 0 && shouldTimeOutLocked()) {
109 onIdle();
110 } else {
111 this->postIdleTimeoutCheck();
112 }
113 }
114
115 void beginUpload() {
116 std::lock_guard _lock{mLock};
117 mPendingUploads++;
118
119 if (!mUploadThread) {
120 mUploadThread = new ThreadBase{};
121 }
122 if (!mUploadThread->isRunning()) {
123 mUploadThread->start("GrallocUploadThread");
124 }
125
126 onBeginUpload();
127 }
128
129 void endUpload() {
130 std::lock_guard _lock{mLock};
131 mPendingUploads--;
132 mLastUpload = systemTime();
133 }
134
135 int mPendingUploads = 0;
136 nsecs_t mLastUpload = 0;
137};
138
139#define FENCE_TIMEOUT 2000000000
140
141class EGLUploader : public AHBUploader {
142private:
Greg Danielc0732522019-02-20 08:31:03 -0500143 void onDestroy() override {
144 mEglManager.destroy();
145 }
146 void onIdle() override {
147 mEglManager.destroy();
148 }
149
150 void onBeginUpload() override {
151 if (!mEglManager.hasEglContext()) {
152 mUploadThread->queue().runSync([this]() {
153 this->mEglManager.initialize();
154 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
155 });
156
157 this->postIdleTimeoutCheck();
158 }
159 }
160
161
162 EGLDisplay getUploadEglDisplay() {
163 std::lock_guard _lock{mLock};
164 LOG_ALWAYS_FATAL_IF(!mEglManager.hasEglContext(), "Forgot to begin an upload?");
165 return mEglManager.eglDisplay();
166 }
167
168 bool onUploadHardwareBitmap(const SkBitmap& bitmap, const FormatInfo& format,
Alec Mouri45238012020-01-29 11:04:40 -0800169 AHardwareBuffer* ahb) override {
Greg Danielc0732522019-02-20 08:31:03 -0500170 ATRACE_CALL();
171
172 EGLDisplay display = getUploadEglDisplay();
173
174 LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
175 uirenderer::renderthread::EglManager::eglErrorString());
Alec Mouri45238012020-01-29 11:04:40 -0800176 // We use an EGLImage to access the content of the buffer
Greg Danielc0732522019-02-20 08:31:03 -0500177 // The EGL image is later bound to a 2D texture
Alec Mouri70463a62020-03-30 15:10:17 -0700178 const EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(ahb);
Greg Danielc0732522019-02-20 08:31:03 -0500179 AutoEglImage autoImage(display, clientBuffer);
180 if (autoImage.image == EGL_NO_IMAGE_KHR) {
181 ALOGW("Could not create EGL image, err =%s",
182 uirenderer::renderthread::EglManager::eglErrorString());
183 return false;
184 }
185
186 {
187 ATRACE_FORMAT("CPU -> gralloc transfer (%dx%d)", bitmap.width(), bitmap.height());
188 EGLSyncKHR fence = mUploadThread->queue().runSync([&]() -> EGLSyncKHR {
189 AutoSkiaGlTexture glTexture;
190 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image);
John Reck996773a2020-02-03 16:30:56 -0800191 if (GLUtils::dumpGLErrors()) {
192 return EGL_NO_SYNC_KHR;
193 }
Greg Danielc0732522019-02-20 08:31:03 -0500194
195 // glTexSubImage2D is synchronous in sense that it memcpy() from pointer that we
196 // provide.
197 // But asynchronous in sense that driver may upload texture onto hardware buffer
198 // when we first use it in drawing
199 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
200 format.format, format.type, bitmap.getPixels());
John Reck996773a2020-02-03 16:30:56 -0800201 if (GLUtils::dumpGLErrors()) {
202 return EGL_NO_SYNC_KHR;
203 }
Greg Danielc0732522019-02-20 08:31:03 -0500204
205 EGLSyncKHR uploadFence =
206 eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_FENCE_KHR, NULL);
John Reck996773a2020-02-03 16:30:56 -0800207 if (uploadFence == EGL_NO_SYNC_KHR) {
208 ALOGW("Could not create sync fence %#x", eglGetError());
209 };
Greg Danielc0732522019-02-20 08:31:03 -0500210 glFlush();
John Reck996773a2020-02-03 16:30:56 -0800211 GLUtils::dumpGLErrors();
Greg Danielc0732522019-02-20 08:31:03 -0500212 return uploadFence;
213 });
214
John Reck996773a2020-02-03 16:30:56 -0800215 if (fence == EGL_NO_SYNC_KHR) {
216 return false;
217 }
Greg Danielc0732522019-02-20 08:31:03 -0500218 EGLint waitStatus = eglClientWaitSyncKHR(display, fence, 0, FENCE_TIMEOUT);
John Reck996773a2020-02-03 16:30:56 -0800219 ALOGE_IF(waitStatus != EGL_CONDITION_SATISFIED_KHR,
220 "Failed to wait for the fence %#x", eglGetError());
Greg Danielc0732522019-02-20 08:31:03 -0500221
222 eglDestroySyncKHR(display, fence);
223 }
224 return true;
225 }
226
227 renderthread::EglManager mEglManager;
228};
229
230class VkUploader : public AHBUploader {
231private:
Greg Danielc0732522019-02-20 08:31:03 -0500232 void onDestroy() override {
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400233 std::lock_guard _lock{mVkLock};
Greg Danielc0732522019-02-20 08:31:03 -0500234 mGrContext.reset();
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400235 mVulkanManagerStrong.clear();
Greg Danielc0732522019-02-20 08:31:03 -0500236 }
237 void onIdle() override {
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400238 onDestroy();
Greg Danielc0732522019-02-20 08:31:03 -0500239 }
John Recke170fb62018-05-07 08:12:07 -0700240
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400241 void onBeginUpload() override {}
John Recke170fb62018-05-07 08:12:07 -0700242
Greg Danielc0732522019-02-20 08:31:03 -0500243 bool onUploadHardwareBitmap(const SkBitmap& bitmap, const FormatInfo& format,
Alec Mouri45238012020-01-29 11:04:40 -0800244 AHardwareBuffer* ahb) override {
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400245 bool uploadSucceeded = false;
246 mUploadThread->queue().runSync([this, &uploadSucceeded, bitmap, ahb]() {
247 ATRACE_CALL();
248 std::lock_guard _lock{mVkLock};
Greg Danielc0732522019-02-20 08:31:03 -0500249
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400250 renderthread::VulkanManager* vkManager = getVulkanManager();
251 if (!vkManager->hasVkContext()) {
252 LOG_ALWAYS_FATAL_IF(mGrContext,
253 "GrContext exists with no VulkanManager for vulkan uploads");
254 vkManager->initialize();
255 }
Greg Danielc0732522019-02-20 08:31:03 -0500256
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400257 if (!mGrContext) {
258 GrContextOptions options;
259 mGrContext = vkManager->createContext(options,
260 renderthread::VulkanManager::ContextType::kUploadThread);
261 LOG_ALWAYS_FATAL_IF(!mGrContext, "failed to create GrContext for vulkan uploads");
262 this->postIdleTimeoutCheck();
263 }
264
265 sk_sp<SkImage> image =
Kevin Lubickdd8b2ea2023-03-17 19:55:58 +0000266 SkImages::TextureFromAHardwareBufferWithData(mGrContext.get(), bitmap.pixmap(),
267 ahb);
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400268 mGrContext->submit(true);
269
270 uploadSucceeded = (image.get() != nullptr);
271 });
272 return uploadSucceeded;
273 }
274
275 /* must be called on the upload thread after the vkLock has been acquired */
276 renderthread::VulkanManager* getVulkanManager() {
277 if (!mVulkanManagerStrong) {
278 mVulkanManagerStrong = mVulkanManagerWeak.promote();
279
280 // create a new manager if we couldn't promote the weak ref
281 if (!mVulkanManagerStrong) {
282 mVulkanManagerStrong = renderthread::VulkanManager::getInstance();
283 mGrContext.reset();
284 mVulkanManagerWeak = mVulkanManagerStrong;
285 }
286 }
287
288 return mVulkanManagerStrong.get();
Greg Danielc0732522019-02-20 08:31:03 -0500289 }
290
Adlai Hollerf8c434e2020-07-27 11:42:45 -0400291 sk_sp<GrDirectContext> mGrContext;
Derek Sollenberger802fefa2020-08-13 16:53:30 -0400292 sp<renderthread::VulkanManager> mVulkanManagerStrong;
293 wp<renderthread::VulkanManager> mVulkanManagerWeak;
Greg Danielc0732522019-02-20 08:31:03 -0500294 std::mutex mVkLock;
295};
John Recke170fb62018-05-07 08:12:07 -0700296
Alec Mouri1efd0a52022-01-20 13:58:23 -0800297static bool checkSupport(AHardwareBuffer_Format format) {
298 AHardwareBuffer_Desc desc = {
299 .width = 1,
300 .height = 1,
301 .layers = 1,
302 .format = format,
303 .usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
304 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
305 };
306 UniqueAHardwareBuffer buffer = allocateAHardwareBuffer(desc);
307 return buffer != nullptr;
308}
309
Leon Scroggins IIIee3bfe72019-01-31 08:42:23 -0500310bool HardwareBitmapUploader::hasFP16Support() {
Alec Mouri1efd0a52022-01-20 13:58:23 -0800311 static bool hasFP16Support = checkSupport(AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT);
John Recke170fb62018-05-07 08:12:07 -0700312 return hasFP16Support;
313}
314
Alec Mouri1efd0a52022-01-20 13:58:23 -0800315bool HardwareBitmapUploader::has1010102Support() {
316 static bool has101012Support = checkSupport(AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM);
317 return has101012Support;
318}
319
Leon Scroggins IIIa008aa92022-03-10 16:25:30 -0500320bool HardwareBitmapUploader::hasAlpha8Support() {
321 static bool hasAlpha8Support = checkSupport(AHARDWAREBUFFER_FORMAT_R8_UNORM);
322 return hasAlpha8Support;
323}
324
Greg Danielc0732522019-02-20 08:31:03 -0500325static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) {
John Recke170fb62018-05-07 08:12:07 -0700326 FormatInfo formatInfo;
John Recke170fb62018-05-07 08:12:07 -0700327 switch (skBitmap.info().colorType()) {
328 case kRGBA_8888_SkColorType:
329 formatInfo.isSupported = true;
Colin Crossf4e74b82019-10-31 13:47:42 -0700330 [[fallthrough]];
John Recke170fb62018-05-07 08:12:07 -0700331 // ARGB_4444 is upconverted to RGBA_8888
332 case kARGB_4444_SkColorType:
Alec Mouri45238012020-01-29 11:04:40 -0800333 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700334 formatInfo.format = GL_RGBA;
335 formatInfo.type = GL_UNSIGNED_BYTE;
Greg Danielc0732522019-02-20 08:31:03 -0500336 formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700337 break;
338 case kRGBA_F16_SkColorType:
Leon Scroggins IIIee3bfe72019-01-31 08:42:23 -0500339 formatInfo.isSupported = HardwareBitmapUploader::hasFP16Support();
John Recke170fb62018-05-07 08:12:07 -0700340 if (formatInfo.isSupported) {
341 formatInfo.type = GL_HALF_FLOAT;
Alec Mouri45238012020-01-29 11:04:40 -0800342 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
Greg Danielc0732522019-02-20 08:31:03 -0500343 formatInfo.vkFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
John Recke170fb62018-05-07 08:12:07 -0700344 } else {
345 formatInfo.type = GL_UNSIGNED_BYTE;
Alec Mouri45238012020-01-29 11:04:40 -0800346 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
Greg Danielc0732522019-02-20 08:31:03 -0500347 formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700348 }
349 formatInfo.format = GL_RGBA;
350 break;
351 case kRGB_565_SkColorType:
352 formatInfo.isSupported = true;
Alec Mouri45238012020-01-29 11:04:40 -0800353 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700354 formatInfo.format = GL_RGB;
355 formatInfo.type = GL_UNSIGNED_SHORT_5_6_5;
Greg Danielc0732522019-02-20 08:31:03 -0500356 formatInfo.vkFormat = VK_FORMAT_R5G6B5_UNORM_PACK16;
John Recke170fb62018-05-07 08:12:07 -0700357 break;
358 case kGray_8_SkColorType:
Greg Danielc0732522019-02-20 08:31:03 -0500359 formatInfo.isSupported = usingGL;
Alec Mouri45238012020-01-29 11:04:40 -0800360 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700361 formatInfo.format = GL_LUMINANCE;
362 formatInfo.type = GL_UNSIGNED_BYTE;
Greg Danielc0732522019-02-20 08:31:03 -0500363 formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
John Recke170fb62018-05-07 08:12:07 -0700364 break;
Alec Mouri1efd0a52022-01-20 13:58:23 -0800365 case kRGBA_1010102_SkColorType:
366 formatInfo.isSupported = HardwareBitmapUploader::has1010102Support();
367 if (formatInfo.isSupported) {
368 formatInfo.type = GL_UNSIGNED_INT_2_10_10_10_REV;
369 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
370 formatInfo.vkFormat = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
371 } else {
372 formatInfo.type = GL_UNSIGNED_BYTE;
373 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
374 formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
375 }
376 formatInfo.format = GL_RGBA;
377 break;
Leon Scroggins IIIa008aa92022-03-10 16:25:30 -0500378 case kAlpha_8_SkColorType:
379 formatInfo.isSupported = HardwareBitmapUploader::hasAlpha8Support();
380 formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8_UNORM;
381 formatInfo.format = GL_R8;
382 formatInfo.type = GL_UNSIGNED_BYTE;
383 formatInfo.vkFormat = VK_FORMAT_R8_UNORM;
384 break;
John Recke170fb62018-05-07 08:12:07 -0700385 default:
386 ALOGW("unable to create hardware bitmap of colortype: %d", skBitmap.info().colorType());
387 formatInfo.valid = false;
388 }
389 return formatInfo;
390}
391
392static SkBitmap makeHwCompatible(const FormatInfo& format, const SkBitmap& source) {
393 if (format.isSupported) {
394 return source;
395 } else {
396 SkBitmap bitmap;
Mike Reed7994a312021-01-28 18:06:26 -0500397 bitmap.allocPixels(source.info().makeColorType(kN32_SkColorType));
398 bitmap.writePixels(source.pixmap());
John Recke170fb62018-05-07 08:12:07 -0700399 return bitmap;
400 }
401}
402
Greg Danielc0732522019-02-20 08:31:03 -0500403
404static void createUploader(bool usingGL) {
405 static std::mutex lock;
406 std::lock_guard _lock{lock};
407 if (!sUploader.get()) {
408 if (usingGL) {
409 sUploader = new EGLUploader();
410 } else {
411 sUploader = new VkUploader();
412 }
413 }
414}
John Recke170fb62018-05-07 08:12:07 -0700415
416sk_sp<Bitmap> HardwareBitmapUploader::allocateHardwareBitmap(const SkBitmap& sourceBitmap) {
417 ATRACE_CALL();
418
Greg Danielc0732522019-02-20 08:31:03 -0500419 bool usingGL = uirenderer::Properties::getRenderPipelineType() ==
420 uirenderer::RenderPipelineType::SkiaGL;
421
422 FormatInfo format = determineFormat(sourceBitmap, usingGL);
John Recke170fb62018-05-07 08:12:07 -0700423 if (!format.valid) {
424 return nullptr;
425 }
426
John Recke170fb62018-05-07 08:12:07 -0700427 SkBitmap bitmap = makeHwCompatible(format, sourceBitmap);
Alec Mouri45238012020-01-29 11:04:40 -0800428 AHardwareBuffer_Desc desc = {
429 .width = static_cast<uint32_t>(bitmap.width()),
430 .height = static_cast<uint32_t>(bitmap.height()),
431 .layers = 1,
432 .format = format.bufferFormat,
433 .usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
434 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
435 };
436 UniqueAHardwareBuffer ahb = allocateAHardwareBuffer(desc);
437 if (!ahb) {
438 ALOGW("allocateHardwareBitmap() failed in AHardwareBuffer_allocate()");
John Recke170fb62018-05-07 08:12:07 -0700439 return nullptr;
Alec Mouri45238012020-01-29 11:04:40 -0800440 };
John Recke170fb62018-05-07 08:12:07 -0700441
Greg Danielc0732522019-02-20 08:31:03 -0500442 createUploader(usingGL);
John Recke170fb62018-05-07 08:12:07 -0700443
Alec Mouri45238012020-01-29 11:04:40 -0800444 if (!sUploader->uploadHardwareBitmap(bitmap, format, ahb.get())) {
John Recke170fb62018-05-07 08:12:07 -0700445 return nullptr;
446 }
Alec Mouri45238012020-01-29 11:04:40 -0800447 return Bitmap::createFrom(ahb.get(), bitmap.colorType(), bitmap.refColorSpace(),
448 bitmap.alphaType(), Bitmap::computePalette(bitmap));
John Recke170fb62018-05-07 08:12:07 -0700449}
450
Greg Danielc0732522019-02-20 08:31:03 -0500451void HardwareBitmapUploader::initialize() {
452 bool usingGL = uirenderer::Properties::getRenderPipelineType() ==
453 uirenderer::RenderPipelineType::SkiaGL;
454 createUploader(usingGL);
Greg Danielc0732522019-02-20 08:31:03 -0500455}
456
John Reck6104cea2019-01-10 14:37:17 -0800457void HardwareBitmapUploader::terminate() {
Greg Daniel78b7ddc2019-03-27 12:52:43 -0400458 if (sUploader) {
459 sUploader->destroy();
460 }
John Reck6104cea2019-01-10 14:37:17 -0800461}
462
Chris Blume7b8a8082018-11-30 15:51:58 -0800463} // namespace android::uirenderer