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 12using android::AHardwareBuffer_convertToGrallocUsageBits; 13using android::dvr::display::DisplayClient; 14using android::dvr::display::Surface; 15using android::dvr::display::SurfaceAttributes; 16using android::dvr::display::SurfaceAttributeValue; 17using android::dvr::CreateDvrReadBufferFromBufferConsumer; 18using android::pdx::rpc::EmptyVariant; 19 20namespace { 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. 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 32bool 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 85extern "C" { 86 87struct DvrSurface { 88 std::unique_ptr<Surface> surface; 89}; 90 91int 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 118void 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, 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 179int 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 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) 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 244int 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