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