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>
ArrayCopy(SurfaceAttributeValue * destination,const T (& source)[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 
ConvertSurfaceAttributes(const DvrSurfaceAttribute * attributes,size_t attribute_count,SurfaceAttributes * surface_attributes,size_t * error_index)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 
dvrSurfaceCreate(const DvrSurfaceAttribute * attributes,size_t attribute_count,DvrSurface ** out_surface)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 
dvrSurfaceDestroy(DvrSurface * surface)117 void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; }
118 
dvrSurfaceGetId(DvrSurface * surface)119 int dvrSurfaceGetId(DvrSurface* surface) {
120   return surface->surface->surface_id();
121 }
122 
dvrSurfaceSetAttributes(DvrSurface * surface,const DvrSurfaceAttribute * attributes,size_t attribute_count)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 
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)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 
dvrSetupGlobalBuffer(DvrGlobalBufferKey key,size_t size,uint64_t usage,DvrBuffer ** buffer_out)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 
dvrDeleteGlobalBuffer(DvrGlobalBufferKey key)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 
dvrGetGlobalBuffer(DvrGlobalBufferKey key,DvrBuffer ** out_buffer)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 
dvrGetNativeDisplayMetrics(size_t sizeof_metrics,DvrNativeDisplayMetrics * metrics)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