blob: e6031b162bda4eb16d2607dea3e04db06ada7424 [file] [log] [blame]
// 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