#include "include/dvr/dvr_surface.h" #include #include #include #include #include "dvr_buffer_queue_internal.h" #include "dvr_internal.h" using android::AHardwareBuffer_convertToGrallocUsageBits; using android::dvr::display::DisplayClient; using android::dvr::display::Surface; using android::dvr::display::SurfaceAttributes; using android::dvr::display::SurfaceAttributeValue; using android::pdx::rpc::EmptyVariant; namespace { // Sets the Variant |destination| to the target std::array type and copies the C // array into it. Unsupported std::array configurations will fail to compile. template void ArrayCopy(SurfaceAttributeValue* destination, const T (&source)[N]) { using ArrayType = std::array; *destination = ArrayType{}; std::copy(std::begin(source), std::end(source), std::get(*destination).begin()); } bool ConvertSurfaceAttributes(const DvrSurfaceAttribute* attributes, size_t attribute_count, SurfaceAttributes* surface_attributes, size_t* error_index) { for (size_t i = 0; i < attribute_count; i++) { SurfaceAttributeValue value; switch (attributes[i].value.type) { case DVR_SURFACE_ATTRIBUTE_TYPE_INT32: value = attributes[i].value.int32_value; break; case DVR_SURFACE_ATTRIBUTE_TYPE_INT64: value = attributes[i].value.int64_value; break; case DVR_SURFACE_ATTRIBUTE_TYPE_BOOL: // bool_value is defined in an extern "C" block, which makes it look // like an int to C++. Use a cast to assign the correct type to the // Variant type SurfaceAttributeValue. value = static_cast(attributes[i].value.bool_value); break; case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT: value = attributes[i].value.float_value; break; case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2: ArrayCopy(&value, attributes[i].value.float2_value); break; case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3: ArrayCopy(&value, attributes[i].value.float3_value); break; case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4: ArrayCopy(&value, attributes[i].value.float4_value); break; case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8: ArrayCopy(&value, attributes[i].value.float8_value); break; case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16: ArrayCopy(&value, attributes[i].value.float16_value); break; case DVR_SURFACE_ATTRIBUTE_TYPE_NONE: value = EmptyVariant{}; break; default: *error_index = i; return false; } surface_attributes->emplace(attributes[i].key, value); } return true; } } // anonymous namespace extern "C" { struct DvrSurface { std::unique_ptr surface; }; int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes, size_t attribute_count, DvrSurface** out_surface) { if (out_surface == nullptr) { ALOGE("dvrSurfaceCreate: Invalid inputs: out_surface=%p.", out_surface); return -EINVAL; } size_t error_index; SurfaceAttributes surface_attributes; if (!ConvertSurfaceAttributes(attributes, attribute_count, &surface_attributes, &error_index)) { ALOGE("dvrSurfaceCreate: Invalid surface attribute type: %" PRIu64, attributes[error_index].value.type); return -EINVAL; } auto status = Surface::CreateSurface(surface_attributes); if (!status) { ALOGE("dvrSurfaceCreate:: Failed to create display surface: %s", status.GetErrorMessage().c_str()); return -status.error(); } *out_surface = new DvrSurface{status.take()}; return 0; } void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; } int dvrSurfaceGetId(DvrSurface* surface) { return surface->surface->surface_id(); } int dvrSurfaceSetAttributes(DvrSurface* surface, const DvrSurfaceAttribute* attributes, size_t attribute_count) { if (surface == nullptr || attributes == nullptr) { ALOGE( "dvrSurfaceSetAttributes: Invalid inputs: surface=%p attributes=%p " "attribute_count=%zu", surface, attributes, attribute_count); return -EINVAL; } size_t error_index; SurfaceAttributes surface_attributes; if (!ConvertSurfaceAttributes(attributes, attribute_count, &surface_attributes, &error_index)) { ALOGE("dvrSurfaceSetAttributes: Invalid surface attribute type: %" PRIu64, attributes[error_index].value.type); return -EINVAL; } auto status = surface->surface->SetAttributes(surface_attributes); if (!status) { ALOGE("dvrSurfaceSetAttributes: Failed to set attributes: %s", status.GetErrorMessage().c_str()); return -status.error(); } return 0; } int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width, uint32_t height, uint32_t format, uint32_t layer_count, uint64_t usage, size_t capacity, size_t metadata_size, DvrWriteBufferQueue** out_writer) { if (surface == nullptr || out_writer == nullptr) { ALOGE( "dvrSurfaceCreateWriteBufferQueue: Invalid inputs: surface=%p, " "out_writer=%p.", surface, out_writer); return -EINVAL; } auto status = surface->surface->CreateQueue( width, height, layer_count, format, usage, capacity, metadata_size); if (!status) { ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s", status.GetErrorMessage().c_str()); return -status.error(); } *out_writer = new DvrWriteBufferQueue(status.take()); return 0; } int dvrSetupGlobalBuffer(DvrGlobalBufferKey key, size_t size, uint64_t usage, DvrBuffer** buffer_out) { if (!buffer_out) return -EINVAL; int error; auto client = DisplayClient::Create(&error); if (!client) { ALOGE("dvrSetupGlobalBuffer: Failed to create display client: %s", strerror(-error)); return error; } uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage); auto buffer_status = client->SetupGlobalBuffer(key, size, gralloc_usage); if (!buffer_status) { ALOGE("dvrSetupGlobalBuffer: Failed to setup global buffer: %s", buffer_status.GetErrorMessage().c_str()); return -buffer_status.error(); } *buffer_out = CreateDvrBufferFromIonBuffer(buffer_status.take()); return 0; } int dvrDeleteGlobalBuffer(DvrGlobalBufferKey key) { int error; auto client = DisplayClient::Create(&error); if (!client) { ALOGE("dvrDeleteGlobalBuffer: Failed to create display client: %s", strerror(-error)); return error; } auto buffer_status = client->DeleteGlobalBuffer(key); if (!buffer_status) { ALOGE("dvrDeleteGlobalBuffer: Failed to delete named buffer: %s", buffer_status.GetErrorMessage().c_str()); return -buffer_status.error(); } return 0; } int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer) { if (!out_buffer) return -EINVAL; int error; auto client = DisplayClient::Create(&error); if (!client) { ALOGE("dvrGetGlobalBuffer: Failed to create display client: %s", strerror(-error)); return error; } auto status = client->GetGlobalBuffer(key); if (!status) { return -status.error(); } *out_buffer = CreateDvrBufferFromIonBuffer(status.take()); return 0; } int dvrGetNativeDisplayMetrics(size_t sizeof_metrics, DvrNativeDisplayMetrics* metrics) { ALOGE_IF(sizeof_metrics != sizeof(DvrNativeDisplayMetrics), "dvrGetNativeDisplayMetrics: metrics struct mismatch, your dvr api " "header is out of date."); auto client = DisplayClient::Create(); if (!client) { ALOGE("dvrGetNativeDisplayMetrics: Failed to create display client!"); return -ECOMM; } if (metrics == nullptr) { ALOGE("dvrGetNativeDisplayMetrics: output metrics buffer must be non-null"); return -EINVAL; } auto status = client->GetDisplayMetrics(); if (!status) { return -status.error(); } if (sizeof_metrics >= 20) { metrics->display_width = status.get().display_width; metrics->display_height = status.get().display_height; metrics->display_x_dpi = status.get().display_x_dpi; metrics->display_y_dpi = status.get().display_y_dpi; metrics->vsync_period_ns = status.get().vsync_period_ns; } return 0; } } // extern "C"