/* * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ #include #include #include "drm_fourcc.h" #include "TestingAndroidWsi.h" namespace gfxstream { static constexpr int numFds = 0; static constexpr int numInts = 1; std::optional 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 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; } TestingAHardwareBuffer::TestingAHardwareBuffer( uint32_t width, uint32_t height, VirtGpuBlobPtr resource) : mWidth(width), mHeight(height), mResource(resource) { mHandle = native_handle_create(numFds, numInts); mHandle->data[0] = mResource->getResourceHandle(); } TestingAHardwareBuffer::~TestingAHardwareBuffer() { native_handle_close(mHandle); } uint32_t TestingAHardwareBuffer::getResourceId() const { return mResource->getResourceHandle(); } uint32_t TestingAHardwareBuffer::getWidth() const { return mWidth; } uint32_t TestingAHardwareBuffer::getHeight() const { return mHeight; } int TestingAHardwareBuffer::getAndroidFormat() const { return /*AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM=*/1; } uint32_t TestingAHardwareBuffer::getDrmFormat() const { return DRM_FORMAT_ABGR8888; } AHardwareBuffer* TestingAHardwareBuffer::asAHardwareBuffer() { return reinterpret_cast(this); } buffer_handle_t TestingAHardwareBuffer::asBufferHandle() { return reinterpret_cast(mHandle); } EGLClientBuffer TestingAHardwareBuffer::asEglClientBuffer() { return reinterpret_cast(this); } TestingVirtGpuGralloc::TestingVirtGpuGralloc() {} uint32_t TestingVirtGpuGralloc::createColorBuffer( void*, int width, int height, uint32_t glFormat) { auto drmFormat = GlFormatToDrmFormat(glFormat); if (!drmFormat) { ALOGE("Unhandled format"); } auto ahb = allocate(width, height, *drmFormat); uint32_t hostHandle = ahb->getResourceId(); mAllocatedColorBuffers.emplace(hostHandle, std::move(ahb)); return hostHandle; } int TestingVirtGpuGralloc::allocate( uint32_t width, uint32_t height, uint32_t format, uint64_t usage, AHardwareBuffer** outputAhb) { (void)width; (void)height; (void)format; (void)usage; (void)outputAhb; // TODO: support export flow? ALOGE("Unimplemented"); return 0; } std::unique_ptr TestingVirtGpuGralloc::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) { std::cout << "Unhandled DRM format:" << 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 std::make_unique(width, height, std::move(resource)); } void TestingVirtGpuGralloc::acquire(AHardwareBuffer* ahb) { // TODO } void TestingVirtGpuGralloc::release(AHardwareBuffer* ahb) { // TODO } uint32_t TestingVirtGpuGralloc::getHostHandle(const native_handle_t* handle) { const auto* ahb = reinterpret_cast(handle); return ahb->getResourceId(); } uint32_t TestingVirtGpuGralloc::getHostHandle(const AHardwareBuffer* handle) { const auto* ahb = reinterpret_cast(handle); return ahb->getResourceId(); } int TestingVirtGpuGralloc::getFormat(const native_handle_t* handle) { const auto* ahb = reinterpret_cast(handle); return ahb->getAndroidFormat(); } int TestingVirtGpuGralloc::getFormat(const AHardwareBuffer* handle) { const auto* ahb = reinterpret_cast(handle); return ahb->getAndroidFormat(); } uint32_t TestingVirtGpuGralloc::getFormatDrmFourcc(const AHardwareBuffer* handle) { const auto* ahb = reinterpret_cast(handle); return ahb->getDrmFormat(); } size_t TestingVirtGpuGralloc::getAllocatedSize(const native_handle_t*) { ALOGE("Unimplemented."); return 0; } size_t TestingVirtGpuGralloc::getAllocatedSize(const AHardwareBuffer*) { ALOGE("Unimplemented."); return 0; } TestingANativeWindow::TestingANativeWindow( uint32_t width, uint32_t height, uint32_t format, std::vector> buffers) : mWidth(width), mHeight(height), mFormat(format), mBuffers(std::move(buffers)) { for (auto& buffer : mBuffers) { mBufferQueue.push_back(QueuedAHB{ .ahb = buffer.get(), .fence = -1, }); } } EGLNativeWindowType TestingANativeWindow::asEglNativeWindowType() { return reinterpret_cast(this); } uint32_t TestingANativeWindow::getWidth() const { return mWidth; } uint32_t TestingANativeWindow::getHeight() const { return mHeight; } int TestingANativeWindow::getFormat() const { return mFormat; } int TestingANativeWindow::queueBuffer(EGLClientBuffer buffer, int fence) { auto ahb = reinterpret_cast(buffer); mBufferQueue.push_back(QueuedAHB{ .ahb = ahb, .fence = fence, }); return 0; } int TestingANativeWindow::dequeueBuffer(EGLClientBuffer* buffer, int* fence) { auto queuedAhb = mBufferQueue.front(); mBufferQueue.pop_front(); *buffer = queuedAhb.ahb->asEglClientBuffer(); *fence = queuedAhb.fence; return 0; } int TestingANativeWindow::cancelBuffer(EGLClientBuffer buffer) { auto ahb = reinterpret_cast(buffer); mBufferQueue.push_back(QueuedAHB{ .ahb = ahb, .fence = -1, }); return 0; } bool TestingVirtGpuANativeWindowHelper::isValid(EGLNativeWindowType window) { // TODO: maybe a registry of valid TestingANativeWindow-s? return true; } bool TestingVirtGpuANativeWindowHelper::isValid(EGLClientBuffer buffer) { // TODO: maybe a registry of valid TestingAHardwareBuffer-s? return true; } void TestingVirtGpuANativeWindowHelper::acquire(EGLNativeWindowType window) { // TODO: maybe a registry of valid TestingANativeWindow-s? } void TestingVirtGpuANativeWindowHelper::release(EGLNativeWindowType window) { // TODO: maybe a registry of valid TestingANativeWindow-s? } void TestingVirtGpuANativeWindowHelper::acquire(EGLClientBuffer buffer) { // TODO: maybe a registry of valid TestingAHardwareBuffer-s? } void TestingVirtGpuANativeWindowHelper::release(EGLClientBuffer buffer) { // TODO: maybe a registry of valid TestingAHardwareBuffer-s? } int TestingVirtGpuANativeWindowHelper::getConsumerUsage(EGLNativeWindowType window, int* usage) { (void)window; (void)usage; return 0; } void TestingVirtGpuANativeWindowHelper::setUsage(EGLNativeWindowType window, int usage) { (void)window; (void)usage; } int TestingVirtGpuANativeWindowHelper::getWidth(EGLNativeWindowType window) { auto anw = reinterpret_cast(window); return anw->getWidth(); } int TestingVirtGpuANativeWindowHelper::getHeight(EGLNativeWindowType window) { auto anw = reinterpret_cast(window); return anw->getHeight(); } int TestingVirtGpuANativeWindowHelper::getWidth(EGLClientBuffer buffer) { auto ahb = reinterpret_cast(buffer); return ahb->getWidth(); } int TestingVirtGpuANativeWindowHelper::getHeight(EGLClientBuffer buffer) { auto ahb = reinterpret_cast(buffer); return ahb->getHeight(); } int TestingVirtGpuANativeWindowHelper::getFormat(EGLClientBuffer buffer, Gralloc* helper) { auto ahb = reinterpret_cast(buffer); return ahb->getAndroidFormat(); } void TestingVirtGpuANativeWindowHelper::setSwapInterval(EGLNativeWindowType window, int interval) { ALOGE("Unimplemented"); } int TestingVirtGpuANativeWindowHelper::queueBuffer(EGLNativeWindowType window, EGLClientBuffer buffer, int fence) { auto anw = reinterpret_cast(window); return anw->queueBuffer(buffer, fence); } int TestingVirtGpuANativeWindowHelper::dequeueBuffer(EGLNativeWindowType window, EGLClientBuffer* buffer, int* fence) { auto anw = reinterpret_cast(window); return anw->dequeueBuffer(buffer, fence); } int TestingVirtGpuANativeWindowHelper::cancelBuffer(EGLNativeWindowType window, EGLClientBuffer buffer) { auto anw = reinterpret_cast(window); return anw->cancelBuffer(buffer); } int TestingVirtGpuANativeWindowHelper::getHostHandle(EGLClientBuffer buffer, Gralloc*) { auto ahb = reinterpret_cast(buffer); return ahb->getResourceId(); } } // namespace gfxstream