Home | History | Annotate | Download | only in libdvr
      1 #include "include/dvr/dvr_surface.h"
      2 
      3 #include <inttypes.h>
      4 
      5 #include <pdx/rpc/variant.h>
      6 #include <private/android/AHardwareBufferHelpers.h>
      7 #include <private/dvr/display_client.h>
      8 
      9 #include "dvr_buffer_queue_internal.h"
     10 #include "dvr_internal.h"
     11 
     12 using android::AHardwareBuffer_convertToGrallocUsageBits;
     13 using android::dvr::display::DisplayClient;
     14 using android::dvr::display::Surface;
     15 using android::dvr::display::SurfaceAttributes;
     16 using android::dvr::display::SurfaceAttributeValue;
     17 using android::pdx::rpc::EmptyVariant;
     18 
     19 namespace {
     20 
     21 // Sets the Variant |destination| to the target std::array type and copies the C
     22 // array into it. Unsupported std::array configurations will fail to compile.
     23 template <typename T, std::size_t N>
     24 void ArrayCopy(SurfaceAttributeValue* destination, const T (&source)[N]) {
     25   using ArrayType = std::array<T, N>;
     26   *destination = ArrayType{};
     27   std::copy(std::begin(source), std::end(source),
     28             std::get<ArrayType>(*destination).begin());
     29 }
     30 
     31 bool ConvertSurfaceAttributes(const DvrSurfaceAttribute* attributes,
     32                               size_t attribute_count,
     33                               SurfaceAttributes* surface_attributes,
     34                               size_t* error_index) {
     35   for (size_t i = 0; i < attribute_count; i++) {
     36     SurfaceAttributeValue value;
     37     switch (attributes[i].value.type) {
     38       case DVR_SURFACE_ATTRIBUTE_TYPE_INT32:
     39         value = attributes[i].value.int32_value;
     40         break;
     41       case DVR_SURFACE_ATTRIBUTE_TYPE_INT64:
     42         value = attributes[i].value.int64_value;
     43         break;
     44       case DVR_SURFACE_ATTRIBUTE_TYPE_BOOL:
     45         // bool_value is defined in an extern "C" block, which makes it look
     46         // like an int to C++. Use a cast to assign the correct type to the
     47         // Variant type SurfaceAttributeValue.
     48         value = static_cast<bool>(attributes[i].value.bool_value);
     49         break;
     50       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT:
     51         value = attributes[i].value.float_value;
     52         break;
     53       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2:
     54         ArrayCopy(&value, attributes[i].value.float2_value);
     55         break;
     56       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3:
     57         ArrayCopy(&value, attributes[i].value.float3_value);
     58         break;
     59       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4:
     60         ArrayCopy(&value, attributes[i].value.float4_value);
     61         break;
     62       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8:
     63         ArrayCopy(&value, attributes[i].value.float8_value);
     64         break;
     65       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16:
     66         ArrayCopy(&value, attributes[i].value.float16_value);
     67         break;
     68       case DVR_SURFACE_ATTRIBUTE_TYPE_NONE:
     69         value = EmptyVariant{};
     70         break;
     71       default:
     72         *error_index = i;
     73         return false;
     74     }
     75 
     76     surface_attributes->emplace(attributes[i].key, value);
     77   }
     78 
     79   return true;
     80 }
     81 
     82 }  // anonymous namespace
     83 
     84 extern "C" {
     85 
     86 struct DvrSurface {
     87   std::unique_ptr<Surface> surface;
     88 };
     89 
     90 int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
     91                      size_t attribute_count, DvrSurface** out_surface) {
     92   if (out_surface == nullptr) {
     93     ALOGE("dvrSurfaceCreate: Invalid inputs: out_surface=%p.", out_surface);
     94     return -EINVAL;
     95   }
     96 
     97   size_t error_index;
     98   SurfaceAttributes surface_attributes;
     99   if (!ConvertSurfaceAttributes(attributes, attribute_count,
    100                                 &surface_attributes, &error_index)) {
    101     ALOGE("dvrSurfaceCreate: Invalid surface attribute type: %" PRIu64,
    102           attributes[error_index].value.type);
    103     return -EINVAL;
    104   }
    105 
    106   auto status = Surface::CreateSurface(surface_attributes);
    107   if (!status) {
    108     ALOGE("dvrSurfaceCreate:: Failed to create display surface: %s",
    109           status.GetErrorMessage().c_str());
    110     return -status.error();
    111   }
    112 
    113   *out_surface = new DvrSurface{status.take()};
    114   return 0;
    115 }
    116 
    117 void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; }
    118 
    119 int dvrSurfaceGetId(DvrSurface* surface) {
    120   return surface->surface->surface_id();
    121 }
    122 
    123 int dvrSurfaceSetAttributes(DvrSurface* surface,
    124                             const DvrSurfaceAttribute* attributes,
    125                             size_t attribute_count) {
    126   if (surface == nullptr || attributes == nullptr) {
    127     ALOGE(
    128         "dvrSurfaceSetAttributes: Invalid inputs: surface=%p attributes=%p "
    129         "attribute_count=%zu",
    130         surface, attributes, attribute_count);
    131     return -EINVAL;
    132   }
    133 
    134   size_t error_index;
    135   SurfaceAttributes surface_attributes;
    136   if (!ConvertSurfaceAttributes(attributes, attribute_count,
    137                                 &surface_attributes, &error_index)) {
    138     ALOGE("dvrSurfaceSetAttributes: Invalid surface attribute type: %" PRIu64,
    139           attributes[error_index].value.type);
    140     return -EINVAL;
    141   }
    142 
    143   auto status = surface->surface->SetAttributes(surface_attributes);
    144   if (!status) {
    145     ALOGE("dvrSurfaceSetAttributes: Failed to set attributes: %s",
    146           status.GetErrorMessage().c_str());
    147     return -status.error();
    148   }
    149 
    150   return 0;
    151 }
    152 
    153 int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
    154                                      uint32_t height, uint32_t format,
    155                                      uint32_t layer_count, uint64_t usage,
    156                                      size_t capacity, size_t metadata_size,
    157                                      DvrWriteBufferQueue** out_writer) {
    158   if (surface == nullptr || out_writer == nullptr) {
    159     ALOGE(
    160         "dvrSurfaceCreateWriteBufferQueue: Invalid inputs: surface=%p, "
    161         "out_writer=%p.",
    162         surface, out_writer);
    163     return -EINVAL;
    164   }
    165 
    166   auto status = surface->surface->CreateQueue(
    167       width, height, layer_count, format, usage, capacity, metadata_size);
    168   if (!status) {
    169     ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s",
    170           status.GetErrorMessage().c_str());
    171     return -status.error();
    172   }
    173 
    174   *out_writer = new DvrWriteBufferQueue(status.take());
    175   return 0;
    176 }
    177 
    178 int dvrSetupGlobalBuffer(DvrGlobalBufferKey key, size_t size, uint64_t usage,
    179                          DvrBuffer** buffer_out) {
    180   if (!buffer_out)
    181     return -EINVAL;
    182 
    183   int error;
    184   auto client = DisplayClient::Create(&error);
    185   if (!client) {
    186     ALOGE("dvrSetupGlobalBuffer: Failed to create display client: %s",
    187           strerror(-error));
    188     return error;
    189   }
    190 
    191   uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
    192 
    193   auto buffer_status = client->SetupGlobalBuffer(key, size, gralloc_usage);
    194   if (!buffer_status) {
    195     ALOGE("dvrSetupGlobalBuffer: Failed to setup global buffer: %s",
    196           buffer_status.GetErrorMessage().c_str());
    197     return -buffer_status.error();
    198   }
    199 
    200   *buffer_out = CreateDvrBufferFromIonBuffer(buffer_status.take());
    201   return 0;
    202 }
    203 
    204 int dvrDeleteGlobalBuffer(DvrGlobalBufferKey key) {
    205   int error;
    206   auto client = DisplayClient::Create(&error);
    207   if (!client) {
    208     ALOGE("dvrDeleteGlobalBuffer: Failed to create display client: %s",
    209           strerror(-error));
    210     return error;
    211   }
    212 
    213   auto buffer_status = client->DeleteGlobalBuffer(key);
    214   if (!buffer_status) {
    215     ALOGE("dvrDeleteGlobalBuffer: Failed to delete named buffer: %s",
    216           buffer_status.GetErrorMessage().c_str());
    217     return -buffer_status.error();
    218   }
    219 
    220   return 0;
    221 }
    222 
    223 int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer) {
    224   if (!out_buffer)
    225     return -EINVAL;
    226 
    227   int error;
    228   auto client = DisplayClient::Create(&error);
    229   if (!client) {
    230     ALOGE("dvrGetGlobalBuffer: Failed to create display client: %s",
    231           strerror(-error));
    232     return error;
    233   }
    234 
    235   auto status = client->GetGlobalBuffer(key);
    236   if (!status) {
    237     return -status.error();
    238   }
    239   *out_buffer = CreateDvrBufferFromIonBuffer(status.take());
    240   return 0;
    241 }
    242 
    243 int dvrGetNativeDisplayMetrics(size_t sizeof_metrics,
    244                                DvrNativeDisplayMetrics* metrics) {
    245   ALOGE_IF(sizeof_metrics != sizeof(DvrNativeDisplayMetrics),
    246            "dvrGetNativeDisplayMetrics: metrics struct mismatch, your dvr api "
    247            "header is out of date.");
    248 
    249   auto client = DisplayClient::Create();
    250   if (!client) {
    251     ALOGE("dvrGetNativeDisplayMetrics: Failed to create display client!");
    252     return -ECOMM;
    253   }
    254 
    255   if (metrics == nullptr) {
    256     ALOGE("dvrGetNativeDisplayMetrics: output metrics buffer must be non-null");
    257     return -EINVAL;
    258   }
    259 
    260   auto status = client->GetDisplayMetrics();
    261 
    262   if (!status) {
    263     return -status.error();
    264   }
    265 
    266   if (sizeof_metrics >= 20) {
    267     metrics->display_width = status.get().display_width;
    268     metrics->display_height = status.get().display_height;
    269     metrics->display_x_dpi = status.get().display_x_dpi;
    270     metrics->display_y_dpi = status.get().display_y_dpi;
    271     metrics->vsync_period_ns = status.get().vsync_period_ns;
    272   }
    273 
    274   return 0;
    275 }
    276 
    277 }  // extern "C"
    278