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