blob: a3a47f10f5537670064406d6bfd8268a39ed0be2 [file] [log] [blame]
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -07001#include "include/dvr/dvr_surface.h"
2
Corey Tabaka2251d822017-04-20 16:04:07 -07003#include <inttypes.h>
4
Corey Tabaka49a706d2017-06-08 14:29:58 -07005#include <pdx/rpc/variant.h>
Corey Tabaka99c2d732017-06-07 17:54:33 -07006#include <private/android/AHardwareBufferHelpers.h>
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -07007#include <private/dvr/display_client.h>
8
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -07009#include "dvr_buffer_queue_internal.h"
Corey Tabaka99c2d732017-06-07 17:54:33 -070010#include "dvr_internal.h"
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -070011
Corey Tabaka99c2d732017-06-07 17:54:33 -070012using android::AHardwareBuffer_convertToGrallocUsageBits;
Corey Tabaka2251d822017-04-20 16:04:07 -070013using android::dvr::display::DisplayClient;
14using android::dvr::display::Surface;
15using android::dvr::display::SurfaceAttributes;
16using android::dvr::display::SurfaceAttributeValue;
17using android::dvr::CreateDvrReadBufferFromBufferConsumer;
Corey Tabaka49a706d2017-06-08 14:29:58 -070018using android::pdx::rpc::EmptyVariant;
Corey Tabaka2251d822017-04-20 16:04:07 -070019
20namespace {
21
Corey Tabaka7190e8a2017-06-22 20:39:42 -070022// 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
Corey Tabaka2251d822017-04-20 16:04:07 -070032bool 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:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070046 // 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);
Corey Tabaka2251d822017-04-20 16:04:07 -070050 break;
51 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT:
52 value = attributes[i].value.float_value;
53 break;
54 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070055 ArrayCopy(&value, attributes[i].value.float2_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070056 break;
57 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070058 ArrayCopy(&value, attributes[i].value.float3_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070059 break;
60 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070061 ArrayCopy(&value, attributes[i].value.float4_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070062 break;
63 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070064 ArrayCopy(&value, attributes[i].value.float8_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070065 break;
66 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070067 ArrayCopy(&value, attributes[i].value.float16_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070068 break;
Corey Tabaka49a706d2017-06-08 14:29:58 -070069 case DVR_SURFACE_ATTRIBUTE_TYPE_NONE:
70 value = EmptyVariant{};
71 break;
Corey Tabaka2251d822017-04-20 16:04:07 -070072 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
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -070084
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -070085extern "C" {
86
Corey Tabaka2251d822017-04-20 16:04:07 -070087struct DvrSurface {
88 std::unique_ptr<Surface> surface;
89};
90
91int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
92 size_t attribute_count, DvrSurface** out_surface) {
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -070093 if (out_surface == nullptr) {
Corey Tabaka2251d822017-04-20 16:04:07 -070094 ALOGE("dvrSurfaceCreate: Invalid inputs: out_surface=%p.", out_surface);
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -070095 return -EINVAL;
96 }
97
Corey Tabaka2251d822017-04-20 16:04:07 -070098 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;
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700105 }
106
Corey Tabaka2251d822017-04-20 16:04:07 -0700107 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 }
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700113
Corey Tabaka2251d822017-04-20 16:04:07 -0700114 *out_surface = new DvrSurface{status.take()};
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700115 return 0;
116}
117
Corey Tabaka2251d822017-04-20 16:04:07 -0700118void 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,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700156 uint32_t layer_count, uint64_t usage,
Jiwen 'Steve' Cai532e5292017-06-02 15:36:44 -0700157 size_t capacity, size_t metadata_size,
Corey Tabaka2251d822017-04-20 16:04:07 -0700158 DvrWriteBufferQueue** out_writer) {
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700159 if (surface == nullptr || out_writer == nullptr) {
160 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -0700161 "dvrSurfaceCreateWriteBufferQueue: Invalid inputs: surface=%p, "
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700162 "out_writer=%p.",
163 surface, out_writer);
164 return -EINVAL;
165 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700166
Corey Tabaka99c2d732017-06-07 17:54:33 -0700167 auto status = surface->surface->CreateQueue(
168 width, height, layer_count, format, usage, capacity, metadata_size);
Corey Tabaka2251d822017-04-20 16:04:07 -0700169 if (!status) {
170 ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s",
171 status.GetErrorMessage().c_str());
172 return -status.error();
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700173 }
174
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700175 *out_writer = new DvrWriteBufferQueue(status.take());
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700176 return 0;
177}
178
Corey Tabaka99c2d732017-06-07 17:54:33 -0700179int 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);
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -0700186 if (!client) {
Corey Tabaka99c2d732017-06-07 17:54:33 -0700187 ALOGE("dvrSetupGlobalBuffer: Failed to create display client: %s",
188 strerror(-error));
189 return error;
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -0700190 }
191
Corey Tabaka99c2d732017-06-07 17:54:33 -0700192 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)
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700226 return -EINVAL;
Corey Tabaka99c2d732017-06-07 17:54:33 -0700227
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;
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700234 }
235
Okan Arikan36d23802017-05-15 15:20:39 -0700236 auto status = client->GetGlobalBuffer(key);
Corey Tabaka2251d822017-04-20 16:04:07 -0700237 if (!status) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700238 return -status.error();
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700239 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700240 *out_buffer = CreateDvrBufferFromIonBuffer(status.take());
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -0700241 return 0;
242}
243
Stephen Kiazykc6033312017-06-09 14:26:31 -0700244int 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
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -0700278} // extern "C"