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
12using android::AHardwareBuffer_convertToGrallocUsageBits;
13using android::dvr::display::DisplayClient;
14using android::dvr::display::Surface;
15using android::dvr::display::SurfaceAttributes;
16using android::dvr::display::SurfaceAttributeValue;
17using android::dvr::CreateDvrReadBufferFromBufferConsumer;
18using android::pdx::rpc::EmptyVariant;
19
20namespace {
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.
24template <typename T, std::size_t N>
25void 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
32bool 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
85extern "C" {
86
87struct DvrSurface {
88  std::unique_ptr<Surface> surface;
89};
90
91int 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
118void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; }
119
120int dvrSurfaceGetId(DvrSurface* surface) {
121  return surface->surface->surface_id();
122}
123
124int 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
154int 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
179int 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
205int 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
224int 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
244int 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