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