blob: 0c7ec0164089c82b238a41b3bd5023b3fd90773b [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;
Corey Tabaka49a706d2017-06-08 14:29:58 -070017using android::pdx::rpc::EmptyVariant;
Corey Tabaka2251d822017-04-20 16:04:07 -070018
19namespace {
20
Corey Tabaka7190e8a2017-06-22 20:39:42 -070021// 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.
23template <typename T, std::size_t N>
24void 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
Corey Tabaka2251d822017-04-20 16:04:07 -070031bool 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:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070045 // 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);
Corey Tabaka2251d822017-04-20 16:04:07 -070049 break;
50 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT:
51 value = attributes[i].value.float_value;
52 break;
53 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070054 ArrayCopy(&value, attributes[i].value.float2_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070055 break;
56 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070057 ArrayCopy(&value, attributes[i].value.float3_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070058 break;
59 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070060 ArrayCopy(&value, attributes[i].value.float4_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070061 break;
62 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070063 ArrayCopy(&value, attributes[i].value.float8_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070064 break;
65 case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16:
Corey Tabaka7190e8a2017-06-22 20:39:42 -070066 ArrayCopy(&value, attributes[i].value.float16_value);
Corey Tabaka2251d822017-04-20 16:04:07 -070067 break;
Corey Tabaka49a706d2017-06-08 14:29:58 -070068 case DVR_SURFACE_ATTRIBUTE_TYPE_NONE:
69 value = EmptyVariant{};
70 break;
Corey Tabaka2251d822017-04-20 16:04:07 -070071 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
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -070083
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -070084extern "C" {
85
Corey Tabaka2251d822017-04-20 16:04:07 -070086struct DvrSurface {
87 std::unique_ptr<Surface> surface;
88};
89
90int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
91 size_t attribute_count, DvrSurface** out_surface) {
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -070092 if (out_surface == nullptr) {
Corey Tabaka2251d822017-04-20 16:04:07 -070093 ALOGE("dvrSurfaceCreate: Invalid inputs: out_surface=%p.", out_surface);
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -070094 return -EINVAL;
95 }
96
Corey Tabaka2251d822017-04-20 16:04:07 -070097 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;
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700104 }
105
Corey Tabaka2251d822017-04-20 16:04:07 -0700106 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 }
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700112
Corey Tabaka2251d822017-04-20 16:04:07 -0700113 *out_surface = new DvrSurface{status.take()};
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700114 return 0;
115}
116
Corey Tabaka2251d822017-04-20 16:04:07 -0700117void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; }
118
119int dvrSurfaceGetId(DvrSurface* surface) {
120 return surface->surface->surface_id();
121}
122
123int 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
153int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
154 uint32_t height, uint32_t format,
Hendrik Wagenaar108e84f2017-05-07 22:19:17 -0700155 uint32_t layer_count, uint64_t usage,
Jiwen 'Steve' Cai532e5292017-06-02 15:36:44 -0700156 size_t capacity, size_t metadata_size,
Corey Tabaka2251d822017-04-20 16:04:07 -0700157 DvrWriteBufferQueue** out_writer) {
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700158 if (surface == nullptr || out_writer == nullptr) {
159 ALOGE(
Corey Tabaka2251d822017-04-20 16:04:07 -0700160 "dvrSurfaceCreateWriteBufferQueue: Invalid inputs: surface=%p, "
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700161 "out_writer=%p.",
162 surface, out_writer);
163 return -EINVAL;
164 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700165
Corey Tabaka99c2d732017-06-07 17:54:33 -0700166 auto status = surface->surface->CreateQueue(
167 width, height, layer_count, format, usage, capacity, metadata_size);
Corey Tabaka2251d822017-04-20 16:04:07 -0700168 if (!status) {
169 ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s",
170 status.GetErrorMessage().c_str());
171 return -status.error();
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700172 }
173
Jiwen 'Steve' Cai656f4062017-05-22 13:02:33 -0700174 *out_writer = new DvrWriteBufferQueue(status.take());
Jiwen 'Steve' Cai74cf0842017-03-23 18:53:16 -0700175 return 0;
176}
177
Corey Tabaka99c2d732017-06-07 17:54:33 -0700178int 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);
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -0700185 if (!client) {
Corey Tabaka99c2d732017-06-07 17:54:33 -0700186 ALOGE("dvrSetupGlobalBuffer: Failed to create display client: %s",
187 strerror(-error));
188 return error;
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -0700189 }
190
Corey Tabaka99c2d732017-06-07 17:54:33 -0700191 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
204int 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
223int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer) {
224 if (!out_buffer)
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700225 return -EINVAL;
Corey Tabaka99c2d732017-06-07 17:54:33 -0700226
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;
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700233 }
234
Okan Arikan36d23802017-05-15 15:20:39 -0700235 auto status = client->GetGlobalBuffer(key);
Corey Tabaka2251d822017-04-20 16:04:07 -0700236 if (!status) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700237 return -status.error();
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700238 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700239 *out_buffer = CreateDvrBufferFromIonBuffer(status.take());
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -0700240 return 0;
241}
242
Stephen Kiazykc6033312017-06-09 14:26:31 -0700243int 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
Jiwen 'Steve' Caibdcee792017-03-22 16:59:53 -0700277} // extern "C"