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