Add IAllocator@3.0 and IMapper@3.0 implementations
This change adds HIDL IAllocator and IMapper to replace
gralloc-based (deprecated) ones.
Bug: 145244672
Bug: 144386336
Test: boot, check if youtube and the virtualscene camera works
Test: CtsNativeHardwareTestCases
Test: CtsDeqpTestCases -t dEQP-VK.api.external*
Change-Id: I380a5a6a6dd88ff9c968ba5f738b3cb6ff93e9e1
Signed-off-by: Roman Kiryanov <rkir@google.com>
diff --git a/Android.mk b/Android.mk
index 2c0a5c2..ce83f67 100644
--- a/Android.mk
+++ b/Android.mk
@@ -149,6 +149,7 @@
include $(GOLDFISH_OPENGL_PATH)/system/GLESv2/Android.mk
include $(GOLDFISH_OPENGL_PATH)/system/gralloc/Android.mk
+include $(GOLDFISH_OPENGL_PATH)/system/hals/Android.mk
include $(GOLDFISH_OPENGL_PATH)/system/cbmanager/Android.mk
include $(GOLDFISH_OPENGL_PATH)/system/egl/Android.mk
diff --git a/system/hals/Android.mk b/system/hals/Android.mk
new file mode 100644
index 0000000..912a362
--- /dev/null
+++ b/system/hals/Android.mk
@@ -0,0 +1,74 @@
+#
+# Copyright 2015 The Android Open-Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android.hardware.graphics.allocator@3.0-service
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := allocator3.cpp
+LOCAL_INIT_RC := android.hardware.graphics.allocator@3.0-service.rc
+
+LOCAL_SHARED_LIBRARIES += \
+ android.hardware.graphics.allocator@3.0 \
+ android.hardware.graphics.mapper@3.0 \
+ libOpenglSystemCommon \
+ libOpenglCodecCommon$(GOLDFISH_OPENGL_LIB_SUFFIX) \
+ libbase \
+ libcutils \
+ libhidlbase \
+ liblog \
+ libutils
+
+LOCAL_C_INCLUDES += \
+ device/generic/goldfish-opengl/system/include \
+ device/generic/goldfish-opengl/system/OpenglSystemCommon \
+ device/generic/goldfish-opengl/shared/OpenglCodecCommon \
+ device/generic/goldfish-opengl/host/include/libOpenglRender \
+ device/generic/goldfish-opengl/system/renderControl_enc \
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android.hardware.graphics.mapper@3.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := mapper3.cpp
+
+# android.hardware.graphics.allocator@3.0 \
+
+LOCAL_SHARED_LIBRARIES += \
+ android.hardware.graphics.mapper@3.0 \
+ libOpenglSystemCommon \
+ libOpenglCodecCommon$(GOLDFISH_OPENGL_LIB_SUFFIX) \
+ libbase \
+ libcutils \
+ libhidlbase \
+ liblog \
+ libutils \
+ libsync
+
+LOCAL_C_INCLUDES += \
+ device/generic/goldfish-opengl/system/include \
+ device/generic/goldfish-opengl/system/OpenglSystemCommon \
+ device/generic/goldfish-opengl/shared/OpenglCodecCommon \
+ device/generic/goldfish-opengl/host/include/libOpenglRender \
+ device/generic/goldfish-opengl/system/renderControl_enc \
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/system/hals/allocator3.cpp b/system/hals/allocator3.cpp
new file mode 100644
index 0000000..e5e182d
--- /dev/null
+++ b/system/hals/allocator3.cpp
@@ -0,0 +1,425 @@
+/*
+* Copyright (C) 2020 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <hidl/LegacySupport.h>
+
+#include "glUtils.h"
+#include "cb_handle_30.h"
+#include "host_connection_session.h"
+#include "types.h"
+#include "debug.h"
+
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_bitfield;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+
+namespace AllocatorV3 = ::android::hardware::graphics::allocator::V3_0;
+namespace MapperV3 = ::android::hardware::graphics::mapper::V3_0;
+
+using IAllocator3 = AllocatorV3::IAllocator;
+using IMapper3 = MapperV3::IMapper;
+using Error3 = MapperV3::Error;
+using BufferDescriptorInfo = IMapper3::BufferDescriptorInfo;
+
+class GoldfishAllocator : public IAllocator3 {
+public:
+ GoldfishAllocator() : m_hostConn(HostConnection::createUnique()) {}
+
+ Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
+ hidl_cb("GoldfishAllocator::dumpDebugInfo is not implemented");
+ return {};
+ }
+
+ Return<void> allocate(const hidl_vec<uint32_t>& rawDescriptor,
+ uint32_t count,
+ allocate_cb hidl_cb) {
+ uint32_t stride = 0;
+ std::vector<cb_handle_30_t*> cbs;
+ cbs.reserve(count);
+
+ const Error3 e = allocateImpl(rawDescriptor, count, &stride, &cbs);
+ if (e == Error3::NONE) {
+ hidl_vec<hidl_handle> handles(cbs.cbegin(), cbs.cend());
+ hidl_cb(Error3::NONE, stride, handles);
+ } else {
+ hidl_cb(e, 0, {});
+ }
+
+ for (cb_handle_30_t* cb : cbs) {
+ freeCb(std::unique_ptr<cb_handle_30_t>(cb));
+ }
+
+ return {};
+ }
+
+private:
+ // this function should be in sync with GoldfishMapper::isSupportedImpl
+ Error3 allocateImpl(const hidl_vec<uint32_t>& rawDescriptor,
+ uint32_t count,
+ uint32_t* pStride,
+ std::vector<cb_handle_30_t*>* cbs) {
+ BufferDescriptorInfo descriptor;
+ if (!decodeBufferDescriptorInfo(rawDescriptor, &descriptor)) {
+ RETURN_ERROR(Error3::BAD_DESCRIPTOR);
+ }
+
+ if (!descriptor.width) { RETURN_ERROR(Error3::UNSUPPORTED); }
+ if (!descriptor.height) { RETURN_ERROR(Error3::UNSUPPORTED); }
+ if (descriptor.layerCount != 1) { RETURN_ERROR(Error3::UNSUPPORTED); }
+
+ const uint32_t usage = descriptor.usage;
+ const bool usageSwWrite = usage & BufferUsage::CPU_WRITE_MASK;
+ const bool usageSwRead = usage & BufferUsage::CPU_READ_MASK;
+ const bool usageHwCamWrite = usage & BufferUsage::CAMERA_OUTPUT;
+ const bool usageHwCamRead = usage & BufferUsage::CAMERA_INPUT;
+
+ int bpp = 1;
+ int glFormat = 0;
+ int glType = 0;
+ int align = 1;
+ bool yuv_format = false;
+ EmulatorFrameworkFormat emulatorFrameworkFormat =
+ EmulatorFrameworkFormat::GL_COMPATIBLE;
+
+ PixelFormat format;
+ Error3 e = getBufferFormat(descriptor.format, usage, &format);
+ if (e != Error3::NONE) {
+ ALOGE("%s:%d Unsupported format: frameworkFormat=%d, usage=%x",
+ __func__, __LINE__, descriptor.format, usage);
+ return e;
+ }
+
+ switch (format) {
+ case PixelFormat::RGBA_8888:
+ case PixelFormat::RGBX_8888:
+ case PixelFormat::BGRA_8888:
+ bpp = 4;
+ glFormat = GL_RGBA;
+ glType = GL_UNSIGNED_BYTE;
+ break;
+
+ case PixelFormat::RGB_888:
+ if (usage & (BufferUsage::GPU_TEXTURE |
+ BufferUsage::GPU_RENDER_TARGET |
+ BufferUsage::COMPOSER_OVERLAY |
+ BufferUsage::COMPOSER_CLIENT_TARGET)) {
+ RETURN_ERROR(Error3::UNSUPPORTED);
+ } else {
+ bpp = 3;
+ glFormat = GL_RGB;
+ glType = GL_UNSIGNED_BYTE;
+ }
+ break;
+
+ case PixelFormat::RGB_565:
+ bpp = 2;
+ glFormat = GL_RGB565;
+ glType = GL_UNSIGNED_SHORT_5_6_5;
+ break;
+
+ case PixelFormat::RGBA_FP16:
+ bpp = 8;
+ glFormat = GL_RGBA16F;
+ glType = GL_HALF_FLOAT;
+ break;
+
+ case PixelFormat::RGBA_1010102:
+ bpp = 4;
+ glFormat = GL_RGB10_A2;
+ glType = GL_UNSIGNED_INT_2_10_10_10_REV;
+ break;
+
+ case PixelFormat::RAW16:
+ case PixelFormat::Y16:
+ bpp = 2;
+ align = 16 * bpp;
+ if (!((usageSwRead || usageHwCamRead) && (usageSwWrite || usageHwCamWrite))) {
+ // Raw sensor data or Y16 only goes between camera and CPU
+ RETURN_ERROR(Error3::UNSUPPORTED);
+ }
+ // Not expecting to actually create any GL surfaces for this
+ glFormat = GL_LUMINANCE;
+ glType = GL_UNSIGNED_SHORT;
+ break;
+
+ case PixelFormat::BLOB:
+ if (!usageSwRead) {
+ // Blob data cannot be used by HW other than camera emulator
+ // But there is a CTS test trying to have access to it
+ // BUG: https://buganizer.corp.google.com/issues/37719518
+ RETURN_ERROR(Error3::UNSUPPORTED);
+ }
+ // Not expecting to actually create any GL surfaces for this
+ glFormat = GL_LUMINANCE;
+ glType = GL_UNSIGNED_BYTE;
+ break;
+
+ case PixelFormat::YCRCB_420_SP:
+ yuv_format = true;
+ // Not expecting to actually create any GL surfaces for this
+ break;
+
+ case PixelFormat::YV12:
+ align = 16;
+ yuv_format = true;
+ // We are going to use RGB8888 on the host for Vulkan
+ glFormat = GL_RGBA;
+ glType = GL_UNSIGNED_BYTE;
+ emulatorFrameworkFormat = EmulatorFrameworkFormat::YV12;
+ break;
+
+ case PixelFormat::YCBCR_420_888:
+ yuv_format = true;
+ // We are going to use RGB888 on the host
+ glFormat = GL_RGB;
+ glType = GL_UNSIGNED_BYTE;
+ emulatorFrameworkFormat = EmulatorFrameworkFormat::YUV_420_888;
+ break;
+
+ default:
+ ALOGE("%s:%d Unsupported format: format=%d, frameworkFormat=%d, usage=%x",
+ __func__, __LINE__, format, descriptor.format, usage);
+ RETURN_ERROR(Error3::UNSUPPORTED);
+ }
+
+ const size_t align1 = align - 1;
+ const uint32_t width = descriptor.width;
+ const uint32_t height = descriptor.height;
+ uint32_t stride;
+ size_t bufferSize;
+
+ if (yuv_format) {
+ const size_t yStride = (width * bpp + align1) & ~align1;
+ const size_t uvStride = (yStride / 2 + align1) & ~align1;
+ const size_t uvHeight = height / 2;
+ bufferSize = yStride * height + 2 * (uvHeight * uvStride);
+ stride = yStride / bpp;
+ } else {
+ const size_t bpr = (width * bpp + align1) & ~align1;
+ bufferSize = bpr * height;
+ stride = bpr / bpp;
+ }
+
+ *pStride = stride;
+
+ return allocateImpl2(usage,
+ width, height,
+ format, emulatorFrameworkFormat,
+ glFormat, glType,
+ bufferSize,
+ bpp, stride,
+ count, cbs);
+ }
+
+ Error3 allocateImpl2(const uint32_t usage,
+ const uint32_t width, const uint32_t height,
+ const PixelFormat format,
+ const EmulatorFrameworkFormat emulatorFrameworkFormat,
+ const int glFormat, const int glType,
+ const size_t bufferSize,
+ const uint32_t bytesPerPixel,
+ const uint32_t stride,
+ const uint32_t count,
+ std::vector<cb_handle_30_t*>* cbs) {
+ for (uint32_t i = 0; i < count; ++i) {
+ cb_handle_30_t* cb;
+ Error3 e = allocateCb(usage,
+ width, height,
+ format, emulatorFrameworkFormat,
+ glFormat, glType,
+ bufferSize,
+ bytesPerPixel, stride,
+ &cb);
+ if (e == Error3::NONE) {
+ cbs->push_back(cb);
+ } else {
+ return e;
+ }
+ }
+
+ RETURN(Error3::NONE);
+ }
+
+ // see GoldfishMapper::encodeBufferDescriptorInfo
+ static bool decodeBufferDescriptorInfo(const hidl_vec<uint32_t>& raw,
+ BufferDescriptorInfo* d) {
+ if (raw.size() == 5) {
+ d->width = raw[0];
+ d->height = raw[1];
+ d->layerCount = raw[2];
+ d->format = static_cast<PixelFormat>(raw[3]);
+ d->usage = raw[4];
+
+ RETURN(true);
+ } else {
+ RETURN_ERROR(false);
+ }
+ }
+
+ static Error3 getBufferFormat(const PixelFormat frameworkFormat,
+ const uint32_t usage,
+ PixelFormat* format) {
+ if (frameworkFormat == PixelFormat::IMPLEMENTATION_DEFINED) {
+ if (usage & BufferUsage::CAMERA_OUTPUT) {
+ if (usage & BufferUsage::GPU_TEXTURE) {
+ // Camera-to-display is RGBA
+ *format = PixelFormat::RGBA_8888;
+ RETURN(Error3::NONE);
+ } else if (usage & BufferUsage::VIDEO_ENCODER) {
+ // Camera-to-encoder is NV21
+ *format = PixelFormat::YCRCB_420_SP;
+ RETURN(Error3::NONE);
+ }
+ }
+ RETURN_ERROR(Error3::UNSUPPORTED);
+ } else {
+ *format = frameworkFormat;
+ RETURN(Error3::NONE);
+ }
+ }
+
+ static bool needHostCb(const uint32_t usage, const PixelFormat format) {
+ return ((usage & BufferUsage::GPU_DATA_BUFFER)
+ || (format != PixelFormat::BLOB &&
+ format != PixelFormat::RAW16 &&
+ format != PixelFormat::Y16))
+ && (usage & (BufferUsage::GPU_TEXTURE
+ | BufferUsage::GPU_RENDER_TARGET
+ | BufferUsage::COMPOSER_OVERLAY
+ | BufferUsage::VIDEO_ENCODER
+ | BufferUsage::COMPOSER_CLIENT_TARGET
+ | BufferUsage::CPU_READ_MASK));
+ }
+
+ Error3 allocateCb(const uint32_t usage,
+ const uint32_t width, const uint32_t height,
+ const PixelFormat format,
+ const EmulatorFrameworkFormat emulatorFrameworkFormat,
+ const int glFormat, const int glType,
+ const size_t bufferSize,
+ const int32_t bytesPerPixel,
+ const int32_t stride,
+ cb_handle_30_t** cb) {
+ GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator;
+ if (!host_memory_allocator.is_opened()) {
+ RETURN_ERROR(Error3::NO_RESOURCES);
+ }
+
+ GoldfishAddressSpaceBlock bufferBits;
+ if (host_memory_allocator.hostMalloc(&bufferBits, bufferSize)) {
+ RETURN_ERROR(Error3::NO_RESOURCES);
+ }
+
+ uint32_t hostHandle = 0;
+ QEMU_PIPE_HANDLE hostHandleRefCountFd = QEMU_PIPE_INVALID_HANDLE;
+ if (needHostCb(usage, format)) {
+ hostHandleRefCountFd = qemu_pipe_open("refcount");
+ if (!qemu_pipe_valid(hostHandleRefCountFd)) {
+ RETURN_ERROR(Error3::NO_RESOURCES);
+ }
+
+ const GLenum allocFormat =
+ (PixelFormat::RGBX_8888 == format) ? GL_RGB : glFormat;
+
+ const HostConnectionSession conn = getHostConnectionSession();
+ ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
+ CRASH_IF(!rcEnc, "conn.getRcEncoder() failed");
+
+ hostHandle = rcEnc->rcCreateColorBufferDMA(
+ rcEnc,
+ width, height,
+ allocFormat, static_cast<int>(emulatorFrameworkFormat));
+
+ if (!hostHandle) {
+ qemu_pipe_close(hostHandleRefCountFd);
+ RETURN_ERROR(Error3::NO_RESOURCES);
+ }
+
+ if (qemu_pipe_write(hostHandleRefCountFd,
+ &hostHandle,
+ sizeof(hostHandle)) != sizeof(hostHandle)) {
+ rcEnc->rcCloseColorBuffer(rcEnc, hostHandle);
+ qemu_pipe_close(hostHandleRefCountFd);
+ RETURN_ERROR(Error3::NO_RESOURCES);
+ }
+ }
+
+ std::unique_ptr<cb_handle_30_t> handle =
+ std::make_unique<cb_handle_30_t>(
+ host_memory_allocator.release(),
+ hostHandleRefCountFd,
+ hostHandle,
+ usage,
+ width,
+ height,
+ static_cast<int>(format),
+ glFormat,
+ glType,
+ bufferSize,
+ bufferBits.guestPtr(),
+ bufferBits.size(),
+ bufferBits.offset(),
+ bytesPerPixel,
+ stride);
+
+ bufferBits.release();
+ *cb = handle.release();
+ RETURN(Error3::NONE);
+ }
+
+ void freeCb(std::unique_ptr<cb_handle_30_t> cb) {
+ // no need to undo .hostMalloc: the kernel will take care of it once the
+ // last bufferFd (duped) is closed.
+
+ if (qemu_pipe_valid(cb->hostHandleRefCountFd)) {
+ qemu_pipe_close(cb->hostHandleRefCountFd);
+ }
+ GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
+ GoldfishAddressSpaceHostMemoryAllocator::closeHandle(cb->bufferFd);
+ }
+
+ HostConnectionSession getHostConnectionSession() const {
+ return HostConnectionSession(m_hostConn);
+ }
+
+ //std::unique_ptr<HostConnection> m_hostConn; // b/142677230
+ HostConnection* m_hostConn;
+};
+
+int main(int, char**) {
+ using ::android::sp;
+
+ ::android::hardware::configureRpcThreadpool(4, true /* callerWillJoin */);
+
+ sp<IAllocator3> allocator(new GoldfishAllocator());
+ if (allocator->registerAsService() != ::android::NO_ERROR) {
+ ALOGE("failed to register graphics IAllocator@3.0 service");
+ return -EINVAL;
+ }
+
+ ALOGI("graphics IAllocator@3.0 service is initialized");
+ ::android::hardware::joinRpcThreadpool();
+
+ ALOGI("graphics IAllocator@3.0 service is terminating");
+ return 0;
+}
diff --git a/system/hals/android.hardware.graphics.allocator@3.0-service.rc b/system/hals/android.hardware.graphics.allocator@3.0-service.rc
new file mode 100644
index 0000000..8b9e13a
--- /dev/null
+++ b/system/hals/android.hardware.graphics.allocator@3.0-service.rc
@@ -0,0 +1,8 @@
+service vendor.gralloc-3-0 /vendor/bin/hw/android.hardware.graphics.allocator@3.0-service
+ interface android.hardware.graphics.allocator@3.0::IAllocator default
+ class hal animation
+ interface android.hardware.graphics.allocator@3.0::IAllocator default
+ user system
+ group graphics drmrpc
+ capabilities SYS_NICE
+ onrestart restart surfaceflinger
diff --git a/system/hals/cb_handle_30.h b/system/hals/cb_handle_30.h
new file mode 100644
index 0000000..11ce322
--- /dev/null
+++ b/system/hals/cb_handle_30.h
@@ -0,0 +1,81 @@
+/*
+* Copyright 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef SYSTEM_HALS_CB_HANDLE_30_H
+#define SYSTEM_HALS_CB_HANDLE_30_H
+
+#include "gralloc_cb.h"
+#include "goldfish_address_space.h"
+
+const uint32_t CB_HANDLE_MAGIC_30 = CB_HANDLE_MAGIC_BASE | 0x2;
+
+struct cb_handle_30_t : public cb_handle_t {
+ cb_handle_30_t(address_space_handle_t p_bufferFd,
+ QEMU_PIPE_HANDLE p_hostHandleRefCountFd,
+ uint32_t p_hostHandle,
+ int32_t p_usage,
+ int32_t p_width,
+ int32_t p_height,
+ int32_t p_format,
+ int32_t p_glFormat,
+ int32_t p_glType,
+ uint32_t p_bufSize,
+ void* p_bufPtr,
+ uint32_t p_mmapedSize,
+ uint64_t p_mmapedOffset,
+ uint32_t p_bytesPerPixel,
+ uint32_t p_stride)
+ : cb_handle_t(p_bufferFd,
+ p_hostHandleRefCountFd,
+ CB_HANDLE_MAGIC_30,
+ p_hostHandle,
+ p_usage,
+ p_width,
+ p_height,
+ p_format,
+ p_glFormat,
+ p_glType,
+ p_bufSize,
+ p_bufPtr,
+ p_mmapedOffset),
+ mmapedSize(p_mmapedSize),
+ bytesPerPixel(p_bytesPerPixel),
+ stride(p_stride) {
+ numInts = CB_HANDLE_NUM_INTS(numFds);
+ }
+
+ bool isValid() const { return (version == sizeof(native_handle_t)) && (magic == CB_HANDLE_MAGIC_30); }
+
+ static cb_handle_30_t* from(void* p) {
+ if (!p) { return nullptr; }
+ cb_handle_30_t* cb = static_cast<cb_handle_30_t*>(p);
+ return cb->isValid() ? cb : nullptr;
+ }
+
+ static const cb_handle_30_t* from(const void* p) {
+ return from(const_cast<void*>(p));
+ }
+
+ static cb_handle_30_t* from_unconst(const void* p) {
+ return from(const_cast<void*>(p));
+ }
+
+ uint32_t mmapedSize; // real allocation side
+ uint32_t bytesPerPixel;
+ uint32_t stride;
+};
+
+#endif // SYSTEM_HALS_CB_HANDLE_30_H
diff --git a/system/hals/debug.h b/system/hals/debug.h
new file mode 100644
index 0000000..f8e41b4
--- /dev/null
+++ b/system/hals/debug.h
@@ -0,0 +1,44 @@
+/*
+* Copyright (C) 2020 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef GOLDFISH_OPENGL_SYSTEM_HALS_DEBUG_H_INCLUDED
+#define GOLDFISH_OPENGL_SYSTEM_HALS_DEBUG_H_INCLUDED
+
+#include <log/log.h>
+
+#define RETURN(X) return (X)
+
+#define RETURN_ERROR(X) \
+ do { \
+ ALOGE("%s:%d failed with '%s'", __func__, __LINE__, #X); \
+ return (X); \
+ } while (false)
+
+#define CRASH(MSG) \
+ do { \
+ ALOGE("%s:%d crashed with '%s'", __func__, __LINE__, MSG); \
+ ::abort(); \
+ } while (false)
+
+#define CRASH_IF(COND, MSG) \
+ do { \
+ if ((COND)) { \
+ ALOGE("%s:%d crashed on '%s' with '%s'", __func__, __LINE__, #COND, MSG); \
+ ::abort(); \
+ } \
+ } while (false)
+
+#endif // GOLDFISH_OPENGL_SYSTEM_HALS_DEBUG_H_INCLUDED
diff --git a/system/hals/host_connection_session.h b/system/hals/host_connection_session.h
new file mode 100644
index 0000000..12d3b76
--- /dev/null
+++ b/system/hals/host_connection_session.h
@@ -0,0 +1,56 @@
+/*
+* Copyright (C) 2020 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef GOLDFISH_OPENGL_SYSTEM_HALS_HOST_CONNECTION_SESSION_H_INCLUDED
+#define GOLDFISH_OPENGL_SYSTEM_HALS_HOST_CONNECTION_SESSION_H_INCLUDED
+
+#include "HostConnection.h"
+
+class HostConnectionSession {
+public:
+ explicit HostConnectionSession(HostConnection* hc) : conn(hc) {
+ hc->lock();
+ }
+
+ ~HostConnectionSession() {
+ if (conn) {
+ conn->unlock();
+ }
+ }
+
+ HostConnectionSession(HostConnectionSession&& rhs) : conn(rhs.conn) {
+ rhs.conn = nullptr;
+ }
+
+ HostConnectionSession& operator=(HostConnectionSession&& rhs) {
+ if (this != &rhs) {
+ std::swap(conn, rhs.conn);
+ }
+ return *this;
+ }
+
+ HostConnectionSession(const HostConnectionSession&) = delete;
+ HostConnectionSession& operator=(const HostConnectionSession&) = delete;
+
+ ExtendedRCEncoderContext* getRcEncoder() const {
+ return conn->rcEncoder();
+ }
+
+private:
+ HostConnection* conn;
+};
+
+#endif // GOLDFISH_OPENGL_SYSTEM_HALS_HOST_CONNECTION_SESSION_H_INCLUDED
diff --git a/system/hals/mapper3.cpp b/system/hals/mapper3.cpp
new file mode 100644
index 0000000..99c6514
--- /dev/null
+++ b/system/hals/mapper3.cpp
@@ -0,0 +1,615 @@
+/*
+* Copyright (C) 2020 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <cutils/native_handle.h>
+#include <sync/sync.h>
+
+#include "cb_handle_30.h"
+#include "host_connection_session.h"
+#include "FormatConversions.h"
+#include "debug.h"
+
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+
+namespace MapperV3 = ::android::hardware::graphics::mapper::V3_0;
+
+using IMapper3 = MapperV3::IMapper;
+using Error3 = MapperV3::Error;
+using YCbCrLayout3 = MapperV3::YCbCrLayout;
+
+namespace {
+size_t align(const size_t v, const size_t a) { return (v + a - 1) & ~(a - 1); }
+
+static int waitFenceFd(const int fd, const char* logname) {
+ const int warningTimeout = 5000;
+ if (sync_wait(dup(fd), warningTimeout) < 0) {
+ if (errno == ETIME) {
+ ALOGW("%s: fence %d didn't signal in %d ms", logname, fd, warningTimeout);
+ if (sync_wait(fd, -1) < 0) {
+ RETURN_ERROR(errno);
+ } else {
+ RETURN(0);
+ }
+ } else {
+ RETURN_ERROR(errno);
+ }
+ } else {
+ RETURN(0);
+ }
+}
+
+int waitHidlFence(const hidl_handle& hidlHandle, const char* logname) {
+ const native_handle_t* nativeHandle = hidlHandle.getNativeHandle();
+
+ if (!nativeHandle) {
+ RETURN(0);
+ }
+ if (nativeHandle->numFds > 1) {
+ RETURN_ERROR(-EINVAL);
+ }
+ if (nativeHandle->numInts != 0) {
+ RETURN_ERROR(-EINVAL);
+ }
+
+ return waitFenceFd(nativeHandle->data[0], logname);
+}
+
+class GoldfishMapper : public IMapper3 {
+public:
+ GoldfishMapper() : m_hostConn(HostConnection::createUnique()) {
+ GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator;
+ CRASH_IF(!host_memory_allocator.is_opened(),
+ "GoldfishAddressSpaceHostMemoryAllocator failed to open");
+
+ GoldfishAddressSpaceBlock bufferBits;
+ CRASH_IF(host_memory_allocator.hostMalloc(&bufferBits, 256),
+ "hostMalloc failed");
+
+ m_physAddrToOffset = bufferBits.physAddr() - bufferBits.offset();
+ }
+
+ Return<void> importBuffer(const hidl_handle& hh,
+ importBuffer_cb hidl_cb) {
+ native_handle_t* imported = nullptr;
+ const Error3 e = importBufferImpl(hh.getNativeHandle(), &imported);
+ if (e == Error3::NONE) {
+ hidl_cb(Error3::NONE, imported);
+ } else {
+ hidl_cb(e, nullptr);
+ }
+ return {};
+ }
+
+ Return<Error3> freeBuffer(void* raw) {
+ if (!raw) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ cb_handle_30_t* cb = cb_handle_30_t::from(raw);
+ if (!cb) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+
+ if (cb->hostHandle) {
+ const HostConnectionSession conn = getHostConnectionSession();
+ ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
+ rcEnc->rcCloseColorBuffer(rcEnc, cb->hostHandle);
+ }
+
+ if (cb->mmapedSize > 0) {
+ GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
+ }
+
+ native_handle_close(cb);
+ native_handle_delete(cb);
+
+ RETURN(Error3::NONE);
+ }
+
+ Return<void> lock(void* raw,
+ uint64_t cpuUsage,
+ const Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ lock_cb hidl_cb) {
+ void* ptr = nullptr;
+ int32_t bytesPerPixel = 0;
+ int32_t bytesPerStride = 0;
+
+ const Error3 e = lockImpl(raw, cpuUsage, accessRegion, acquireFence,
+ &ptr, &bytesPerPixel, &bytesPerStride);
+ if (e == Error3::NONE) {
+ hidl_cb(Error3::NONE, ptr, bytesPerPixel, bytesPerStride);
+ } else {
+ hidl_cb(e, nullptr, 0, 0);
+ }
+ return {};
+ }
+
+ Return<void> lockYCbCr(void* raw,
+ uint64_t cpuUsage,
+ const Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ lockYCbCr_cb hidl_cb) {
+ YCbCrLayout3 ycbcr = {};
+ const Error3 e = lockYCbCrImpl(raw, cpuUsage, accessRegion, acquireFence,
+ &ycbcr);
+ if (e == Error3::NONE) {
+ hidl_cb(Error3::NONE, ycbcr);
+ } else {
+ hidl_cb(e, {});
+ }
+ return {};
+ }
+
+ Return<void> unlock(void* raw, unlock_cb hidl_cb) {
+ hidl_cb(unlockImpl(raw), {});
+ return {};
+
+ }
+
+ Return<void> createDescriptor(const BufferDescriptorInfo& description,
+ createDescriptor_cb hidl_cb) {
+ hidl_vec<uint32_t> raw;
+ encodeBufferDescriptorInfo(description, &raw);
+ hidl_cb(Error3::NONE, raw);
+ return {};
+ }
+
+ Return<void> isSupported(const IMapper::BufferDescriptorInfo& description,
+ isSupported_cb hidl_cb) {
+ hidl_cb(Error3::NONE, isSupportedImpl(description));
+ return {};
+ }
+
+ Return<Error3> validateBufferSize(void* buffer,
+ const BufferDescriptorInfo& descriptor,
+ uint32_t stride) {
+ const cb_handle_30_t* cb = cb_handle_30_t::from(buffer);
+ if (cb) {
+ return validateBufferSizeImpl(*cb, descriptor, stride);
+ } else {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ }
+
+ Return<void> getTransportSize(void* buffer,
+ getTransportSize_cb hidl_cb) {
+ const cb_handle_30_t* cb = cb_handle_30_t::from(buffer);
+ if (cb) {
+ hidl_cb(Error3::NONE, cb->numFds, cb->numInts);
+ } else {
+ hidl_cb(Error3::BAD_BUFFER, 0, 0);
+ }
+
+ return {};
+ }
+
+private: // **** impl ****
+ Error3 importBufferImpl(const native_handle_t* nh, native_handle_t** phandle) {
+ if (!nh) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ native_handle_t* imported = native_handle_clone(nh);
+ if (!imported) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ cb_handle_30_t* cb = cb_handle_30_t::from(imported);
+ if (!cb) {
+ native_handle_close(imported);
+ native_handle_delete(imported);
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+
+ if (cb->mmapedSize > 0) {
+ void* ptr;
+ const int res = GoldfishAddressSpaceBlock::memoryMap(
+ cb->getBufferPtr(),
+ cb->mmapedSize,
+ cb->bufferFd,
+ cb->getMmapedOffset(),
+ &ptr);
+ if (res) {
+ native_handle_close(imported);
+ native_handle_delete(imported);
+ RETURN_ERROR(Error3::NO_RESOURCES);
+ }
+ cb->setBufferPtr(ptr);
+ }
+
+ if (cb->hostHandle) {
+ const HostConnectionSession conn = getHostConnectionSession();
+ ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
+ rcEnc->rcOpenColorBuffer2(rcEnc, cb->hostHandle);
+ }
+
+ *phandle = imported;
+ RETURN(Error3::NONE);
+ }
+
+ Error3 lockImpl(void* raw,
+ uint64_t cpuUsage,
+ const Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ void** pptr,
+ int32_t* pBytesPerPixel,
+ int32_t* pBytesPerStride) {
+ if (!raw) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ cb_handle_30_t* cb = cb_handle_30_t::from(raw);
+ if (!cb) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ if (!cb->bufferSize) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ char* const bufferBits = static_cast<char*>(cb->getBufferPtr());
+ if (!bufferBits) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ if (waitHidlFence(acquireFence, __func__)) {
+ RETURN_ERROR(Error3::BAD_VALUE);
+ }
+
+ if (cb->hostHandle) {
+ const Error3 e = lockHostImpl(*cb, cpuUsage, accessRegion, bufferBits);
+ if (e != Error3::NONE) {
+ return e;
+ }
+ }
+
+ *pptr = bufferBits;
+ *pBytesPerPixel = cb->bytesPerPixel;
+ *pBytesPerStride = cb->bytesPerPixel * cb->stride;
+ RETURN(Error3::NONE);
+ }
+
+ Error3 lockYCbCrImpl(void* raw,
+ uint64_t cpuUsage,
+ const Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ YCbCrLayout3* pYcbcr) {
+ if (!raw) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ cb_handle_30_t* cb = cb_handle_30_t::from(raw);
+ if (!cb) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ if (!cb->bufferSize) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ char* const bufferBits = static_cast<char*>(cb->getBufferPtr());
+ if (!bufferBits) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ if (waitHidlFence(acquireFence, __func__)) {
+ RETURN_ERROR(Error3::BAD_VALUE);
+ }
+
+ size_t uOffset;
+ size_t vOffset;
+ size_t yStride;
+ size_t cStride;
+ size_t cStep;
+ switch (static_cast<PixelFormat>(cb->format)) {
+ case PixelFormat::YCRCB_420_SP:
+ yStride = cb->width;
+ cStride = yStride;
+ vOffset = yStride * cb->height;
+ uOffset = vOffset + 1;
+ cStep = 2;
+ break;
+
+ case PixelFormat::YV12:
+ // https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12
+ yStride = align(cb->width, 16);
+ cStride = align(yStride / 2, 16);
+ vOffset = yStride * cb->height;
+ uOffset = vOffset + (cStride * cb->height / 2);
+ cStep = 1;
+ break;
+
+ case PixelFormat::YCBCR_420_888:
+ yStride = cb->width;
+ cStride = yStride / 2;
+ uOffset = cb->height * yStride;
+ vOffset = uOffset + cStride * cb->height / 2;
+ cStep = 1;
+ break;
+
+ default:
+ ALOGE("%s:%d unexpected format (%d)", __func__, __LINE__, cb->format);
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+
+ if (cb->hostHandle) {
+ const Error3 e = lockHostImpl(*cb, cpuUsage, accessRegion, bufferBits);
+ if (e != Error3::NONE) {
+ return e;
+ }
+ }
+
+ pYcbcr->y = bufferBits;
+ pYcbcr->cb = bufferBits + uOffset;
+ pYcbcr->cr = bufferBits + vOffset;
+ pYcbcr->yStride = yStride;
+ pYcbcr->cStride = cStride;
+ pYcbcr->chromaStep = cStep;
+
+ RETURN(Error3::NONE);
+ }
+
+ Error3 lockHostImpl(cb_handle_30_t& cb,
+ const uint32_t usage,
+ const Rect& accessRegion,
+ char* const bufferBits) {
+ const bool usageSwRead = usage & BufferUsage::CPU_READ_MASK;
+ const bool usageSwWrite = usage & BufferUsage::CPU_WRITE_MASK;
+ const bool usageHwCamera = usage & (BufferUsage::CAMERA_INPUT | BufferUsage::CAMERA_OUTPUT);
+ const bool usageHwCameraWrite = usage & BufferUsage::CAMERA_OUTPUT;
+
+ const HostConnectionSession conn = getHostConnectionSession();
+ ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
+
+ const int res = rcEnc->rcColorBufferCacheFlush(
+ rcEnc, cb.hostHandle, 0, usageSwRead);
+ if (res < 0) {
+ RETURN_ERROR(Error3::NO_RESOURCES);
+ }
+
+ // camera delivers bits to the buffer directly and does not require
+ // an explicit read.
+ if (usageSwRead && !usageHwCamera) {
+ if (gralloc_is_yuv_format(cb.format)) {
+ if (rcEnc->hasYUVCache()) {
+ uint32_t bufferSize;
+ switch (static_cast<PixelFormat>(cb.format)) {
+ case PixelFormat::YV12:
+ get_yv12_offsets(cb.width, cb.height,
+ nullptr, nullptr, &bufferSize);
+ break;
+ case PixelFormat::YCBCR_420_888:
+ get_yuv420p_offsets(cb.width, cb.height,
+ nullptr, nullptr, &bufferSize);
+ break;
+ default:
+ CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
+ break;
+ }
+
+ rcEnc->rcReadColorBufferYUV(rcEnc, cb.hostHandle,
+ 0, 0, cb.width, cb.height,
+ bufferBits, bufferSize);
+ } else {
+ // We are using RGB888
+ std::vector<char> tmpBuf(cb.width * cb.height * 3);
+ rcEnc->rcReadColorBuffer(rcEnc, cb.hostHandle,
+ 0, 0, cb.width, cb.height,
+ cb.glFormat, cb.glType,
+ tmpBuf.data());
+ switch (static_cast<PixelFormat>(cb.format)) {
+ case PixelFormat::YV12:
+ rgb888_to_yv12(bufferBits, tmpBuf.data(),
+ cb.width, cb.height,
+ accessRegion.left,
+ accessRegion.top,
+ accessRegion.left + accessRegion.width - 1,
+ accessRegion.top + accessRegion.height - 1);
+ break;
+ case PixelFormat::YCBCR_420_888:
+ rgb888_to_yuv420p(bufferBits, tmpBuf.data(),
+ cb.width, cb.height,
+ accessRegion.left,
+ accessRegion.top,
+ accessRegion.left + accessRegion.width - 1,
+ accessRegion.top + accessRegion.height - 1);
+ break;
+ default:
+ CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
+ break;
+ }
+ }
+ } else {
+ rcEnc->rcReadColorBuffer(rcEnc,
+ cb.hostHandle,
+ 0, 0, cb.width, cb.height,
+ cb.glFormat, cb.glType,
+ bufferBits);
+ }
+ }
+
+ if (usageSwWrite || usageHwCameraWrite) {
+ cb.lockedLeft = accessRegion.left;
+ cb.lockedTop = accessRegion.top;
+ cb.lockedWidth = accessRegion.width;
+ cb.lockedHeight = accessRegion.height;
+ } else {
+ cb.lockedLeft = 0;
+ cb.lockedTop = 0;
+ cb.lockedWidth = cb.width;
+ cb.lockedHeight = cb.height;
+ }
+
+ RETURN(Error3::NONE);
+ }
+
+ Error3 unlockImpl(void* raw) {
+ if (!raw) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ cb_handle_30_t* cb = cb_handle_30_t::from(raw);
+ if (!cb) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ if (!cb->bufferSize) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+ char* const bufferBits = static_cast<char*>(cb->getBufferPtr());
+ if (!bufferBits) {
+ RETURN_ERROR(Error3::BAD_BUFFER);
+ }
+
+ if (cb->hostHandle) {
+ unlockHostImpl(*cb, bufferBits);
+ }
+
+ RETURN(Error3::NONE);
+ }
+
+ void unlockHostImpl(cb_handle_30_t& cb, char* const bufferBits) {
+ const int bpp = glUtilsPixelBitSize(cb.glFormat, cb.glType) >> 3;
+ const int left = cb.lockedLeft;
+ const int top = cb.lockedTop;
+ const int width = cb.lockedWidth;
+ const int height = cb.lockedHeight;
+ const uint32_t rgbSize = width * height * bpp;
+ std::vector<char> convertedBuf;
+ const char* bitsToSend;
+ uint32_t sizeToSend;
+
+ if (gralloc_is_yuv_format(cb.format)) {
+ bitsToSend = bufferBits;
+ switch (static_cast<PixelFormat>(cb.format)) {
+ case PixelFormat::YV12:
+ get_yv12_offsets(width, height, nullptr, nullptr, &sizeToSend);
+ break;
+ case PixelFormat::YCBCR_420_888:
+ get_yuv420p_offsets(width, height, nullptr, nullptr, &sizeToSend);
+ break;
+ default:
+ CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
+ break;
+ }
+ } else {
+ convertedBuf.resize(rgbSize);
+ copy_rgb_buffer_from_unlocked(
+ convertedBuf.data(), bufferBits,
+ cb.width,
+ width, height, top, left, bpp);
+ bitsToSend = convertedBuf.data();
+ sizeToSend = rgbSize;
+ }
+
+ {
+ const HostConnectionSession conn = getHostConnectionSession();
+ ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
+ rcEnc->bindDmaDirectly(bufferBits,
+ getMmapedPhysAddr(cb.getMmapedOffset()));
+ rcEnc->rcUpdateColorBufferDMA(rcEnc, cb.hostHandle,
+ left, top, width, height,
+ cb.glFormat, cb.glType,
+ const_cast<char*>(bitsToSend), sizeToSend);
+ }
+
+ cb.lockedLeft = 0;
+ cb.lockedTop = 0;
+ cb.lockedWidth = 0;
+ cb.lockedHeight = 0;
+ }
+
+ bool isSupportedImpl(const IMapper::BufferDescriptorInfo& descriptor) const {
+ if (!descriptor.width) { RETURN(false); }
+ if (!descriptor.height) { RETURN(false); }
+ if (descriptor.layerCount != 1) { RETURN(false); }
+
+ const uint32_t usage = descriptor.usage;
+ const bool usageSwWrite = usage & BufferUsage::CPU_WRITE_MASK;
+ const bool usageSwRead = usage & BufferUsage::CPU_READ_MASK;
+ const bool usageHwCamWrite = usage & BufferUsage::CAMERA_OUTPUT;
+ const bool usageHwCamRead = usage & BufferUsage::CAMERA_INPUT;
+
+ switch (descriptor.format) {
+ case PixelFormat::RGBA_8888:
+ case PixelFormat::RGBX_8888:
+ case PixelFormat::BGRA_8888:
+ case PixelFormat::RGB_565:
+ case PixelFormat::RGBA_FP16:
+ case PixelFormat::RGBA_1010102:
+ case PixelFormat::YCRCB_420_SP:
+ case PixelFormat::YV12:
+ case PixelFormat::YCBCR_420_888:
+ RETURN(true);
+
+ case PixelFormat::IMPLEMENTATION_DEFINED:
+ if (usage & BufferUsage::CAMERA_OUTPUT) {
+ if (usage & BufferUsage::GPU_TEXTURE) {
+ RETURN(true);
+ } else if (usage & BufferUsage::VIDEO_ENCODER) {
+ RETURN(true);
+ }
+ }
+ RETURN(false);
+
+ case PixelFormat::RGB_888:
+ RETURN(0 == (usage & (BufferUsage::GPU_TEXTURE |
+ BufferUsage::GPU_RENDER_TARGET |
+ BufferUsage::COMPOSER_OVERLAY |
+ BufferUsage::COMPOSER_CLIENT_TARGET)));
+
+ case PixelFormat::RAW16:
+ case PixelFormat::Y16:
+ RETURN((usageSwRead || usageHwCamRead) &&
+ (usageSwWrite || usageHwCamWrite));
+
+ case PixelFormat::BLOB:
+ RETURN(usageSwRead);
+
+ default:
+ RETURN(false);
+ }
+ }
+
+ Error3 validateBufferSizeImpl(const cb_handle_t& /*cb*/,
+ const BufferDescriptorInfo& /*descriptor*/,
+ uint32_t /*stride*/) {
+ RETURN(Error3::NONE);
+ }
+
+ HostConnectionSession getHostConnectionSession() const {
+ return HostConnectionSession(m_hostConn);
+ }
+
+ static void encodeBufferDescriptorInfo(const BufferDescriptorInfo& d,
+ hidl_vec<uint32_t>* raw) {
+ raw->resize(5);
+
+ (*raw)[0] = d.width;
+ (*raw)[1] = d.height;
+ (*raw)[2] = d.layerCount;
+ (*raw)[3] = static_cast<uint32_t>(d.format);
+ (*raw)[4] = d.usage & UINT32_MAX;
+ }
+
+ uint64_t getMmapedPhysAddr(uint64_t offset) const {
+ return m_physAddrToOffset + offset;
+ }
+
+ //std::unique_ptr<HostConnection> m_hostConn; // b/142677230
+ HostConnection* m_hostConn;
+ uint64_t m_physAddrToOffset;
+};
+} // namespace
+
+extern "C" IMapper3* HIDL_FETCH_IMapper(const char* /*name*/) {
+ return new GoldfishMapper;
+}
diff --git a/system/hals/types.h b/system/hals/types.h
new file mode 100644
index 0000000..c7d2646
--- /dev/null
+++ b/system/hals/types.h
@@ -0,0 +1,43 @@
+/*
+* Copyright (C) 2020 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef GOLDFISH_OPENGL_SYSTEM_HALS_TYPES_H_INCLUDED
+#define GOLDFISH_OPENGL_SYSTEM_HALS_TYPES_H_INCLUDED
+
+/* Tell the emulator which formats need special handling. */
+enum class EmulatorFrameworkFormat {
+ GL_COMPATIBLE = 0,
+ YV12 = 1,
+ YUV_420_888 = 2, // (Y+)(U+)(V+)
+};
+
+#ifndef GL_RGBA16F
+#define GL_RGBA16F 0x881A
+#endif // GL_RGBA16F
+
+#ifndef GL_HALF_FLOAT
+#define GL_HALF_FLOAT 0x140B
+#endif // GL_HALF_FLOAT
+
+#ifndef GL_RGB10_A2
+#define GL_RGB10_A2 0x8059
+#endif // GL_RGB10_A2
+
+#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#endif // GL_UNSIGNED_INT_2_10_10_10_REV
+
+#endif // GOLDFISH_OPENGL_SYSTEM_HALS_TYPES_H_INCLUDED