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> 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 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 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 117 void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; } 118 119 int dvrSurfaceGetId(DvrSurface* surface) { 120 return surface->surface->surface_id(); 121 } 122 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 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 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 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 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 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