blob: b62ff18417fca597ffac47279279ed34fc4c11b8 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
#include <iostream>
#include <cutils/log.h>
#include "drm_fourcc.h"
#include "TestingAndroidWsi.h"
namespace gfxstream {
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;
}
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<AHardwareBuffer*>(this);
}
buffer_handle_t TestingAHardwareBuffer::asBufferHandle() {
return reinterpret_cast<buffer_handle_t>(mHandle);
}
EGLClientBuffer TestingAHardwareBuffer::asEglClientBuffer() {
return reinterpret_cast<EGLClientBuffer>(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<TestingAHardwareBuffer> 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<TestingAHardwareBuffer>(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<const TestingAHardwareBuffer*>(handle);
return ahb->getResourceId();
}
uint32_t TestingVirtGpuGralloc::getHostHandle(const AHardwareBuffer* handle) {
const auto* ahb = reinterpret_cast<const TestingAHardwareBuffer*>(handle);
return ahb->getResourceId();
}
int TestingVirtGpuGralloc::getFormat(const native_handle_t* handle) {
const auto* ahb = reinterpret_cast<const TestingAHardwareBuffer*>(handle);
return ahb->getAndroidFormat();
}
int TestingVirtGpuGralloc::getFormat(const AHardwareBuffer* handle) {
const auto* ahb = reinterpret_cast<const TestingAHardwareBuffer*>(handle);
return ahb->getAndroidFormat();
}
uint32_t TestingVirtGpuGralloc::getFormatDrmFourcc(const AHardwareBuffer* handle) {
const auto* ahb = reinterpret_cast<const TestingAHardwareBuffer*>(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<std::unique_ptr<TestingAHardwareBuffer>> 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<EGLNativeWindowType>(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<TestingAHardwareBuffer*>(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<TestingAHardwareBuffer*>(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<TestingANativeWindow*>(window);
return anw->getWidth();
}
int TestingVirtGpuANativeWindowHelper::getHeight(EGLNativeWindowType window) {
auto anw = reinterpret_cast<TestingANativeWindow*>(window);
return anw->getHeight();
}
int TestingVirtGpuANativeWindowHelper::getWidth(EGLClientBuffer buffer) {
auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(buffer);
return ahb->getWidth();
}
int TestingVirtGpuANativeWindowHelper::getHeight(EGLClientBuffer buffer) {
auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(buffer);
return ahb->getHeight();
}
int TestingVirtGpuANativeWindowHelper::getFormat(EGLClientBuffer buffer, Gralloc* helper) {
auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(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<TestingANativeWindow*>(window);
return anw->queueBuffer(buffer, fence);
}
int TestingVirtGpuANativeWindowHelper::dequeueBuffer(EGLNativeWindowType window, EGLClientBuffer* buffer, int* fence) {
auto anw = reinterpret_cast<TestingANativeWindow*>(window);
return anw->dequeueBuffer(buffer, fence);
}
int TestingVirtGpuANativeWindowHelper::cancelBuffer(EGLNativeWindowType window, EGLClientBuffer buffer) {
auto anw = reinterpret_cast<TestingANativeWindow*>(window);
return anw->cancelBuffer(buffer);
}
int TestingVirtGpuANativeWindowHelper::getHostHandle(EGLClientBuffer buffer, Gralloc*) {
auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(buffer);
return ahb->getResourceId();
}
} // namespace gfxstream