| #include "include/dvr/dvr_surface.h" | 
 |  | 
 | #include <inttypes.h> | 
 |  | 
 | #include <private/dvr/display_client.h> | 
 |  | 
 | #include "dvr_internal.h" | 
 |  | 
 | using android::dvr::display::DisplayClient; | 
 | using android::dvr::display::Surface; | 
 | using android::dvr::display::SurfaceAttributes; | 
 | using android::dvr::display::SurfaceAttributeValue; | 
 | using android::dvr::CreateDvrReadBufferFromBufferConsumer; | 
 | using android::dvr::CreateDvrWriteBufferQueueFromProducerQueue; | 
 |  | 
 | namespace { | 
 |  | 
 | 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: | 
 |         value = 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: | 
 |         value = attributes[i].value.float2_value; | 
 |         break; | 
 |       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3: | 
 |         value = attributes[i].value.float3_value; | 
 |         break; | 
 |       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4: | 
 |         value = attributes[i].value.float4_value; | 
 |         break; | 
 |       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8: | 
 |         value = attributes[i].value.float8_value; | 
 |         break; | 
 |       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16: | 
 |         value = attributes[i].value.float16_value; | 
 |         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> 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, | 
 |                                      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); | 
 |   if (!status) { | 
 |     ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s", | 
 |           status.GetErrorMessage().c_str()); | 
 |     return -status.error(); | 
 |   } | 
 |  | 
 |   *out_writer = CreateDvrWriteBufferQueueFromProducerQueue(status.take()); | 
 |   return 0; | 
 | } | 
 |  | 
 | int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) { | 
 |   auto client = DisplayClient::Create(); | 
 |   if (!client) { | 
 |     ALOGE("dvrGetNamedBuffer: Failed to create display client!"); | 
 |     return -ECOMM; | 
 |   } | 
 |  | 
 |   if (out_buffer == nullptr || name == nullptr) { | 
 |     ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name, | 
 |           out_buffer); | 
 |     return -EINVAL; | 
 |   } | 
 |  | 
 |   auto status = client->GetNamedBuffer(name); | 
 |   if (!status) { | 
 |     ALOGE("dvrGetNamedBuffer: Failed to find named buffer name=%s: %s", name, | 
 |           status.GetErrorMessage().c_str()); | 
 |     return -status.error(); | 
 |   } | 
 |   *out_buffer = CreateDvrBufferFromIonBuffer(status.take()); | 
 |   return 0; | 
 | } | 
 |  | 
 | }  // extern "C" |