| // Copyright 2024 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 "GrallocEmulated.h" | |
| #include <cutils/log.h> | |
| #include <optional> | |
| #include "drm_fourcc.h" | |
| namespace gfxstream { | |
| namespace { | |
| static constexpr int numFds = 0; | |
| static constexpr int numInts = 1; | |
| std::optional<uint32_t> GlFormatToDrmFormat(uint32_t glFormat) { | |
| switch (glFormat) { | |
| case kGlRGB: | |
| return DRM_FORMAT_BGR888; | |
| case kGlRGB565: | |
| return DRM_FORMAT_BGR565; | |
| case kGlRGBA: | |
| return DRM_FORMAT_ABGR8888; | |
| } | |
| return std::nullopt; | |
| } | |
| std::optional<uint32_t> DrmToVirglFormat(uint32_t drmFormat) { | |
| switch (drmFormat) { | |
| case DRM_FORMAT_ABGR8888: | |
| return VIRGL_FORMAT_B8G8R8A8_UNORM; | |
| case DRM_FORMAT_BGR888: | |
| return VIRGL_FORMAT_R8G8B8_UNORM; | |
| case DRM_FORMAT_BGR565: | |
| return VIRGL_FORMAT_B5G6R5_UNORM; | |
| } | |
| return std::nullopt; | |
| } | |
| } // namespace | |
| EmulatedAHardwareBuffer::EmulatedAHardwareBuffer(uint32_t width, uint32_t height, | |
| VirtGpuBlobPtr resource) | |
| : mRefCount(1), mWidth(width), mHeight(height), mResource(resource) {} | |
| EmulatedAHardwareBuffer::~EmulatedAHardwareBuffer() {} | |
| uint32_t EmulatedAHardwareBuffer::getResourceId() const { return mResource->getResourceHandle(); } | |
| uint32_t EmulatedAHardwareBuffer::getWidth() const { return mWidth; } | |
| uint32_t EmulatedAHardwareBuffer::getHeight() const { return mHeight; } | |
| int EmulatedAHardwareBuffer::getAndroidFormat() const { | |
| return /*AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM=*/1; | |
| } | |
| uint32_t EmulatedAHardwareBuffer::getDrmFormat() const { return DRM_FORMAT_ABGR8888; } | |
| AHardwareBuffer* EmulatedAHardwareBuffer::asAHardwareBuffer() { | |
| return reinterpret_cast<AHardwareBuffer*>(this); | |
| } | |
| buffer_handle_t EmulatedAHardwareBuffer::asBufferHandle() { | |
| return reinterpret_cast<buffer_handle_t>(this); | |
| } | |
| EGLClientBuffer EmulatedAHardwareBuffer::asEglClientBuffer() { | |
| return reinterpret_cast<EGLClientBuffer>(this); | |
| } | |
| void EmulatedAHardwareBuffer::acquire() { ++mRefCount; } | |
| void EmulatedAHardwareBuffer::release() { | |
| --mRefCount; | |
| if (mRefCount == 0) { | |
| delete this; | |
| } | |
| } | |
| EmulatedGralloc::EmulatedGralloc() {} | |
| uint32_t EmulatedGralloc::createColorBuffer(void*, int width, int height, uint32_t glFormat) { | |
| auto drmFormat = GlFormatToDrmFormat(glFormat); | |
| if (!drmFormat) { | |
| ALOGE("Unhandled format"); | |
| } | |
| auto ahb = allocate(width, height, *drmFormat); | |
| EmulatedAHardwareBuffer* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb); | |
| mOwned.emplace_back(rahb); | |
| return rahb->getResourceId(); | |
| } | |
| int EmulatedGralloc::allocate(uint32_t width, uint32_t height, uint32_t format, uint64_t usage, | |
| AHardwareBuffer** outputAhb) { | |
| (void)usage; | |
| *outputAhb = allocate(width, height, format); | |
| return 0; | |
| } | |
| AHardwareBuffer* EmulatedGralloc::allocate(uint32_t width, uint32_t height, uint32_t format) { | |
| ALOGE("Allocating AHB w:%u, h:%u, format %u", width, height, format); | |
| auto device = VirtGpuDevice::getInstance(); | |
| if (!device) { | |
| ALOGE("Failed to allocate: no virtio gpu device."); | |
| return nullptr; | |
| } | |
| auto virglFormat = DrmToVirglFormat(format); | |
| if (!virglFormat) { | |
| ALOGE("Unhandled DRM format:%u", format); | |
| return nullptr; | |
| } | |
| auto resource = device->createVirglBlob(width, height, *virglFormat); | |
| if (!resource) { | |
| ALOGE("Failed to allocate: failed to create virtio resource."); | |
| return nullptr; | |
| } | |
| resource->wait(); | |
| return reinterpret_cast<AHardwareBuffer*>( | |
| new EmulatedAHardwareBuffer(width, height, std::move(resource))); | |
| } | |
| void EmulatedGralloc::acquire(AHardwareBuffer* ahb) { | |
| auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb); | |
| rahb->acquire(); | |
| } | |
| void EmulatedGralloc::release(AHardwareBuffer* ahb) { | |
| auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb); | |
| rahb->release(); | |
| } | |
| uint32_t EmulatedGralloc::getHostHandle(const native_handle_t* handle) { | |
| const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle); | |
| return ahb->getResourceId(); | |
| } | |
| uint32_t EmulatedGralloc::getHostHandle(const AHardwareBuffer* handle) { | |
| const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle); | |
| return ahb->getResourceId(); | |
| } | |
| const native_handle_t* EmulatedGralloc::getNativeHandle(const AHardwareBuffer* ahb) { | |
| return reinterpret_cast<const native_handle_t*>(ahb); | |
| } | |
| int EmulatedGralloc::getFormat(const native_handle_t* handle) { | |
| const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle); | |
| return ahb->getAndroidFormat(); | |
| } | |
| int EmulatedGralloc::getFormat(const AHardwareBuffer* handle) { | |
| const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle); | |
| return ahb->getAndroidFormat(); | |
| } | |
| uint32_t EmulatedGralloc::getFormatDrmFourcc(const AHardwareBuffer* handle) { | |
| const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle); | |
| return ahb->getDrmFormat(); | |
| } | |
| size_t EmulatedGralloc::getAllocatedSize(const native_handle_t*) { | |
| ALOGE("Unimplemented."); | |
| return 0; | |
| } | |
| size_t EmulatedGralloc::getAllocatedSize(const AHardwareBuffer*) { | |
| ALOGE("Unimplemented."); | |
| return 0; | |
| } | |
| int EmulatedGralloc::getId(const AHardwareBuffer* ahb, uint64_t* id) { | |
| const auto* rahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(ahb); | |
| *id = rahb->getResourceId(); | |
| return 0; | |
| } | |
| Gralloc* createPlatformGralloc(int /*deviceFd*/) { | |
| return new EmulatedGralloc(); | |
| } | |
| } // namespace gfxstream |