1 /* 2 * Copyright 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <algorithm> 18 19 #include <grallocusage/GrallocUsageConversion.h> 20 #include <log/log.h> 21 #include <ui/BufferQueueDefs.h> 22 #include <sync/sync.h> 23 #include <utils/StrongPointer.h> 24 #include <utils/Vector.h> 25 #include <system/window.h> 26 27 #include "driver.h" 28 29 // TODO(jessehall): Currently we don't have a good error code for when a native 30 // window operation fails. Just returning INITIALIZATION_FAILED for now. Later 31 // versions (post SDK 0.9) of the API/extension have a better error code. 32 // When updating to that version, audit all error returns. 33 namespace vulkan { 34 namespace driver { 35 36 namespace { 37 38 const VkSurfaceTransformFlagsKHR kSupportedTransforms = 39 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR | 40 VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | 41 VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR | 42 VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR | 43 // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform. 44 // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR | 45 // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR | 46 // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR | 47 // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR | 48 VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR; 49 50 VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) { 51 // Native and Vulkan transforms are isomorphic, but are represented 52 // differently. Vulkan transforms are built up of an optional horizontal 53 // mirror, followed by a clockwise 0/90/180/270-degree rotation. Native 54 // transforms are built up from a horizontal flip, vertical flip, and 55 // 90-degree rotation, all optional but always in that order. 56 57 // TODO(jessehall): For now, only support pure rotations, not 58 // flip or flip-and-rotate, until I have more time to test them and build 59 // sample code. As far as I know we never actually use anything besides 60 // pure rotations anyway. 61 62 switch (native) { 63 case 0: // 0x0 64 return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 65 // case NATIVE_WINDOW_TRANSFORM_FLIP_H: // 0x1 66 // return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR; 67 // case NATIVE_WINDOW_TRANSFORM_FLIP_V: // 0x2 68 // return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR; 69 case NATIVE_WINDOW_TRANSFORM_ROT_180: // FLIP_H | FLIP_V 70 return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR; 71 case NATIVE_WINDOW_TRANSFORM_ROT_90: // 0x4 72 return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR; 73 // case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90: 74 // return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR; 75 // case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90: 76 // return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR; 77 case NATIVE_WINDOW_TRANSFORM_ROT_270: // FLIP_H | FLIP_V | ROT_90 78 return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR; 79 case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY: 80 default: 81 return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 82 } 83 } 84 85 int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) { 86 switch (transform) { 87 case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: 88 return NATIVE_WINDOW_TRANSFORM_ROT_270; 89 case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: 90 return NATIVE_WINDOW_TRANSFORM_ROT_180; 91 case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: 92 return NATIVE_WINDOW_TRANSFORM_ROT_90; 93 // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform. 94 // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR: 95 // return NATIVE_WINDOW_TRANSFORM_FLIP_H; 96 // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR: 97 // return NATIVE_WINDOW_TRANSFORM_FLIP_H | 98 // NATIVE_WINDOW_TRANSFORM_ROT_90; 99 // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR: 100 // return NATIVE_WINDOW_TRANSFORM_FLIP_V; 101 // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR: 102 // return NATIVE_WINDOW_TRANSFORM_FLIP_V | 103 // NATIVE_WINDOW_TRANSFORM_ROT_90; 104 case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: 105 case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR: 106 default: 107 return 0; 108 } 109 } 110 111 class TimingInfo { 112 public: 113 TimingInfo() = default; 114 TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId) 115 : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0}, 116 native_frame_id_(nativeFrameId) {} 117 bool ready() const { 118 return (timestamp_desired_present_time_ != 119 NATIVE_WINDOW_TIMESTAMP_PENDING && 120 timestamp_actual_present_time_ != 121 NATIVE_WINDOW_TIMESTAMP_PENDING && 122 timestamp_render_complete_time_ != 123 NATIVE_WINDOW_TIMESTAMP_PENDING && 124 timestamp_composition_latch_time_ != 125 NATIVE_WINDOW_TIMESTAMP_PENDING); 126 } 127 void calculate(int64_t rdur) { 128 bool anyTimestampInvalid = 129 (timestamp_actual_present_time_ == 130 NATIVE_WINDOW_TIMESTAMP_INVALID) || 131 (timestamp_render_complete_time_ == 132 NATIVE_WINDOW_TIMESTAMP_INVALID) || 133 (timestamp_composition_latch_time_ == 134 NATIVE_WINDOW_TIMESTAMP_INVALID); 135 if (anyTimestampInvalid) { 136 ALOGE("Unexpectedly received invalid timestamp."); 137 vals_.actualPresentTime = 0; 138 vals_.earliestPresentTime = 0; 139 vals_.presentMargin = 0; 140 return; 141 } 142 143 vals_.actualPresentTime = 144 static_cast<uint64_t>(timestamp_actual_present_time_); 145 int64_t margin = (timestamp_composition_latch_time_ - 146 timestamp_render_complete_time_); 147 // Calculate vals_.earliestPresentTime, and potentially adjust 148 // vals_.presentMargin. The initial value of vals_.earliestPresentTime 149 // is vals_.actualPresentTime. If we can subtract rdur (the duration 150 // of a refresh cycle) from vals_.earliestPresentTime (and also from 151 // vals_.presentMargin) and still leave a positive margin, then we can 152 // report to the application that it could have presented earlier than 153 // it did (per the extension specification). If for some reason, we 154 // can do this subtraction repeatedly, we do, since 155 // vals_.earliestPresentTime really is supposed to be the "earliest". 156 int64_t early_time = timestamp_actual_present_time_; 157 while ((margin > rdur) && 158 ((early_time - rdur) > timestamp_composition_latch_time_)) { 159 early_time -= rdur; 160 margin -= rdur; 161 } 162 vals_.earliestPresentTime = static_cast<uint64_t>(early_time); 163 vals_.presentMargin = static_cast<uint64_t>(margin); 164 } 165 void get_values(VkPastPresentationTimingGOOGLE* values) const { 166 *values = vals_; 167 } 168 169 public: 170 VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 }; 171 172 uint64_t native_frame_id_ { 0 }; 173 int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING }; 174 int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING }; 175 int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING }; 176 int64_t timestamp_composition_latch_time_ 177 { NATIVE_WINDOW_TIMESTAMP_PENDING }; 178 }; 179 180 // ---------------------------------------------------------------------------- 181 182 struct Surface { 183 android::sp<ANativeWindow> window; 184 VkSwapchainKHR swapchain_handle; 185 }; 186 187 VkSurfaceKHR HandleFromSurface(Surface* surface) { 188 return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface)); 189 } 190 191 Surface* SurfaceFromHandle(VkSurfaceKHR handle) { 192 return reinterpret_cast<Surface*>(handle); 193 } 194 195 // Maximum number of TimingInfo structs to keep per swapchain: 196 enum { MAX_TIMING_INFOS = 10 }; 197 // Minimum number of frames to look for in the past (so we don't cause 198 // syncronous requests to Surface Flinger): 199 enum { MIN_NUM_FRAMES_AGO = 5 }; 200 201 struct Swapchain { 202 Swapchain(Surface& surface_, 203 uint32_t num_images_, 204 VkPresentModeKHR present_mode) 205 : surface(surface_), 206 num_images(num_images_), 207 mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR), 208 frame_timestamps_enabled(false), 209 shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR || 210 present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) { 211 ANativeWindow* window = surface.window.get(); 212 native_window_get_refresh_cycle_duration( 213 window, 214 &refresh_duration); 215 } 216 217 Surface& surface; 218 uint32_t num_images; 219 bool mailbox_mode; 220 bool frame_timestamps_enabled; 221 int64_t refresh_duration; 222 bool shared; 223 224 struct Image { 225 Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {} 226 VkImage image; 227 android::sp<ANativeWindowBuffer> buffer; 228 // The fence is only valid when the buffer is dequeued, and should be 229 // -1 any other time. When valid, we own the fd, and must ensure it is 230 // closed: either by closing it explicitly when queueing the buffer, 231 // or by passing ownership e.g. to ANativeWindow::cancelBuffer(). 232 int dequeue_fence; 233 bool dequeued; 234 } images[android::BufferQueueDefs::NUM_BUFFER_SLOTS]; 235 236 android::Vector<TimingInfo> timing; 237 }; 238 239 VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) { 240 return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain)); 241 } 242 243 Swapchain* SwapchainFromHandle(VkSwapchainKHR handle) { 244 return reinterpret_cast<Swapchain*>(handle); 245 } 246 247 void ReleaseSwapchainImage(VkDevice device, 248 ANativeWindow* window, 249 int release_fence, 250 Swapchain::Image& image) { 251 ALOG_ASSERT(release_fence == -1 || image.dequeued, 252 "ReleaseSwapchainImage: can't provide a release fence for " 253 "non-dequeued images"); 254 255 if (image.dequeued) { 256 if (release_fence >= 0) { 257 // We get here from vkQueuePresentKHR. The application is 258 // responsible for creating an execution dependency chain from 259 // vkAcquireNextImage (dequeue_fence) to vkQueuePresentKHR 260 // (release_fence), so we can drop the dequeue_fence here. 261 if (image.dequeue_fence >= 0) 262 close(image.dequeue_fence); 263 } else { 264 // We get here during swapchain destruction, or various serious 265 // error cases e.g. when we can't create the release_fence during 266 // vkQueuePresentKHR. In non-error cases, the dequeue_fence should 267 // have already signalled, since the swapchain images are supposed 268 // to be idle before the swapchain is destroyed. In error cases, 269 // there may be rendering in flight to the image, but since we 270 // weren't able to create a release_fence, waiting for the 271 // dequeue_fence is about the best we can do. 272 release_fence = image.dequeue_fence; 273 } 274 image.dequeue_fence = -1; 275 276 if (window) { 277 window->cancelBuffer(window, image.buffer.get(), release_fence); 278 } else { 279 if (release_fence >= 0) { 280 sync_wait(release_fence, -1 /* forever */); 281 close(release_fence); 282 } 283 } 284 285 image.dequeued = false; 286 } 287 288 if (image.image) { 289 GetData(device).driver.DestroyImage(device, image.image, nullptr); 290 image.image = VK_NULL_HANDLE; 291 } 292 293 image.buffer.clear(); 294 } 295 296 void OrphanSwapchain(VkDevice device, Swapchain* swapchain) { 297 if (swapchain->surface.swapchain_handle != HandleFromSwapchain(swapchain)) 298 return; 299 for (uint32_t i = 0; i < swapchain->num_images; i++) { 300 if (!swapchain->images[i].dequeued) 301 ReleaseSwapchainImage(device, nullptr, -1, swapchain->images[i]); 302 } 303 swapchain->surface.swapchain_handle = VK_NULL_HANDLE; 304 swapchain->timing.clear(); 305 } 306 307 uint32_t get_num_ready_timings(Swapchain& swapchain) { 308 if (swapchain.timing.size() < MIN_NUM_FRAMES_AGO) { 309 return 0; 310 } 311 312 uint32_t num_ready = 0; 313 const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1; 314 for (uint32_t i = 0; i < num_timings; i++) { 315 TimingInfo& ti = swapchain.timing.editItemAt(i); 316 if (ti.ready()) { 317 // This TimingInfo is ready to be reported to the user. Add it 318 // to the num_ready. 319 num_ready++; 320 continue; 321 } 322 // This TimingInfo is not yet ready to be reported to the user, 323 // and so we should look for any available timestamps that 324 // might make it ready. 325 int64_t desired_present_time = 0; 326 int64_t render_complete_time = 0; 327 int64_t composition_latch_time = 0; 328 int64_t actual_present_time = 0; 329 // Obtain timestamps: 330 int ret = native_window_get_frame_timestamps( 331 swapchain.surface.window.get(), ti.native_frame_id_, 332 &desired_present_time, &render_complete_time, 333 &composition_latch_time, 334 NULL, //&first_composition_start_time, 335 NULL, //&last_composition_start_time, 336 NULL, //&composition_finish_time, 337 // TODO(ianelliott): Maybe ask if this one is 338 // supported, at startup time (since it may not be 339 // supported): 340 &actual_present_time, 341 NULL, //&dequeue_ready_time, 342 NULL /*&reads_done_time*/); 343 344 if (ret != android::NO_ERROR) { 345 continue; 346 } 347 348 // Record the timestamp(s) we received, and then see if this TimingInfo 349 // is ready to be reported to the user: 350 ti.timestamp_desired_present_time_ = desired_present_time; 351 ti.timestamp_actual_present_time_ = actual_present_time; 352 ti.timestamp_render_complete_time_ = render_complete_time; 353 ti.timestamp_composition_latch_time_ = composition_latch_time; 354 355 if (ti.ready()) { 356 // The TimingInfo has received enough timestamps, and should now 357 // use those timestamps to calculate the info that should be 358 // reported to the user: 359 ti.calculate(swapchain.refresh_duration); 360 num_ready++; 361 } 362 } 363 return num_ready; 364 } 365 366 // TODO(ianelliott): DEAL WITH RETURN VALUE (e.g. VK_INCOMPLETE)!!! 367 void copy_ready_timings(Swapchain& swapchain, 368 uint32_t* count, 369 VkPastPresentationTimingGOOGLE* timings) { 370 if (swapchain.timing.empty()) { 371 *count = 0; 372 return; 373 } 374 375 size_t last_ready = swapchain.timing.size() - 1; 376 while (!swapchain.timing[last_ready].ready()) { 377 if (last_ready == 0) { 378 *count = 0; 379 return; 380 } 381 last_ready--; 382 } 383 384 uint32_t num_copied = 0; 385 size_t num_to_remove = 0; 386 for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) { 387 const TimingInfo& ti = swapchain.timing[i]; 388 if (ti.ready()) { 389 ti.get_values(&timings[num_copied]); 390 num_copied++; 391 } 392 num_to_remove++; 393 } 394 395 // Discard old frames that aren't ready if newer frames are ready. 396 // We don't expect to get the timing info for those old frames. 397 swapchain.timing.removeItemsAt(0, num_to_remove); 398 399 *count = num_copied; 400 } 401 402 android_pixel_format GetNativePixelFormat(VkFormat format) { 403 android_pixel_format native_format = HAL_PIXEL_FORMAT_RGBA_8888; 404 switch (format) { 405 case VK_FORMAT_R8G8B8A8_UNORM: 406 case VK_FORMAT_R8G8B8A8_SRGB: 407 native_format = HAL_PIXEL_FORMAT_RGBA_8888; 408 break; 409 case VK_FORMAT_R5G6B5_UNORM_PACK16: 410 native_format = HAL_PIXEL_FORMAT_RGB_565; 411 break; 412 case VK_FORMAT_R16G16B16A16_SFLOAT: 413 native_format = HAL_PIXEL_FORMAT_RGBA_FP16; 414 break; 415 case VK_FORMAT_A2R10G10B10_UNORM_PACK32: 416 native_format = HAL_PIXEL_FORMAT_RGBA_1010102; 417 break; 418 default: 419 ALOGV("unsupported swapchain format %d", format); 420 break; 421 } 422 return native_format; 423 } 424 425 android_dataspace GetNativeDataspace(VkColorSpaceKHR colorspace) { 426 switch (colorspace) { 427 case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR: 428 return HAL_DATASPACE_V0_SRGB; 429 case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT: 430 return HAL_DATASPACE_DISPLAY_P3; 431 case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT: 432 return HAL_DATASPACE_V0_SCRGB_LINEAR; 433 case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT: 434 return HAL_DATASPACE_V0_SCRGB; 435 case VK_COLOR_SPACE_DCI_P3_LINEAR_EXT: 436 return HAL_DATASPACE_DCI_P3_LINEAR; 437 case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT: 438 return HAL_DATASPACE_DCI_P3; 439 case VK_COLOR_SPACE_BT709_LINEAR_EXT: 440 return HAL_DATASPACE_V0_SRGB_LINEAR; 441 case VK_COLOR_SPACE_BT709_NONLINEAR_EXT: 442 return HAL_DATASPACE_V0_SRGB; 443 case VK_COLOR_SPACE_BT2020_LINEAR_EXT: 444 return HAL_DATASPACE_BT2020_LINEAR; 445 case VK_COLOR_SPACE_HDR10_ST2084_EXT: 446 return static_cast<android_dataspace>( 447 HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 | 448 HAL_DATASPACE_RANGE_FULL); 449 case VK_COLOR_SPACE_DOLBYVISION_EXT: 450 return static_cast<android_dataspace>( 451 HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 | 452 HAL_DATASPACE_RANGE_FULL); 453 case VK_COLOR_SPACE_HDR10_HLG_EXT: 454 return static_cast<android_dataspace>( 455 HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_HLG | 456 HAL_DATASPACE_RANGE_FULL); 457 case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT: 458 return static_cast<android_dataspace>( 459 HAL_DATASPACE_STANDARD_ADOBE_RGB | 460 HAL_DATASPACE_TRANSFER_LINEAR | HAL_DATASPACE_RANGE_FULL); 461 case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT: 462 return HAL_DATASPACE_ADOBE_RGB; 463 464 // Pass through is intended to allow app to provide data that is passed 465 // to the display system without modification. 466 case VK_COLOR_SPACE_PASS_THROUGH_EXT: 467 return HAL_DATASPACE_ARBITRARY; 468 469 default: 470 // This indicates that we don't know about the 471 // dataspace specified and we should indicate that 472 // it's unsupported 473 return HAL_DATASPACE_UNKNOWN; 474 } 475 } 476 477 } // anonymous namespace 478 479 VKAPI_ATTR 480 VkResult CreateAndroidSurfaceKHR( 481 VkInstance instance, 482 const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, 483 const VkAllocationCallbacks* allocator, 484 VkSurfaceKHR* out_surface) { 485 if (!allocator) 486 allocator = &GetData(instance).allocator; 487 void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Surface), 488 alignof(Surface), 489 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 490 if (!mem) 491 return VK_ERROR_OUT_OF_HOST_MEMORY; 492 Surface* surface = new (mem) Surface; 493 494 surface->window = pCreateInfo->window; 495 surface->swapchain_handle = VK_NULL_HANDLE; 496 497 // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN. 498 int err = 499 native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL); 500 if (err != 0) { 501 // TODO(jessehall): Improve error reporting. Can we enumerate possible 502 // errors and translate them to valid Vulkan result codes? 503 ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err), 504 err); 505 surface->~Surface(); 506 allocator->pfnFree(allocator->pUserData, surface); 507 return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR; 508 } 509 510 *out_surface = HandleFromSurface(surface); 511 return VK_SUCCESS; 512 } 513 514 VKAPI_ATTR 515 void DestroySurfaceKHR(VkInstance instance, 516 VkSurfaceKHR surface_handle, 517 const VkAllocationCallbacks* allocator) { 518 Surface* surface = SurfaceFromHandle(surface_handle); 519 if (!surface) 520 return; 521 native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL); 522 ALOGV_IF(surface->swapchain_handle != VK_NULL_HANDLE, 523 "destroyed VkSurfaceKHR 0x%" PRIx64 524 " has active VkSwapchainKHR 0x%" PRIx64, 525 reinterpret_cast<uint64_t>(surface_handle), 526 reinterpret_cast<uint64_t>(surface->swapchain_handle)); 527 surface->~Surface(); 528 if (!allocator) 529 allocator = &GetData(instance).allocator; 530 allocator->pfnFree(allocator->pUserData, surface); 531 } 532 533 VKAPI_ATTR 534 VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/, 535 uint32_t /*queue_family*/, 536 VkSurfaceKHR /*surface*/, 537 VkBool32* supported) { 538 *supported = VK_TRUE; 539 return VK_SUCCESS; 540 } 541 542 VKAPI_ATTR 543 VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR( 544 VkPhysicalDevice /*pdev*/, 545 VkSurfaceKHR surface, 546 VkSurfaceCapabilitiesKHR* capabilities) { 547 int err; 548 ANativeWindow* window = SurfaceFromHandle(surface)->window.get(); 549 550 int width, height; 551 err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width); 552 if (err != 0) { 553 ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", 554 strerror(-err), err); 555 return VK_ERROR_SURFACE_LOST_KHR; 556 } 557 err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height); 558 if (err != 0) { 559 ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", 560 strerror(-err), err); 561 return VK_ERROR_SURFACE_LOST_KHR; 562 } 563 564 int transform_hint; 565 err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint); 566 if (err != 0) { 567 ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)", 568 strerror(-err), err); 569 return VK_ERROR_SURFACE_LOST_KHR; 570 } 571 572 // TODO(jessehall): Figure out what the min/max values should be. 573 capabilities->minImageCount = 2; 574 capabilities->maxImageCount = 3; 575 576 capabilities->currentExtent = 577 VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)}; 578 579 // TODO(jessehall): Figure out what the max extent should be. Maximum 580 // texture dimension maybe? 581 capabilities->minImageExtent = VkExtent2D{1, 1}; 582 capabilities->maxImageExtent = VkExtent2D{4096, 4096}; 583 584 capabilities->maxImageArrayLayers = 1; 585 586 capabilities->supportedTransforms = kSupportedTransforms; 587 capabilities->currentTransform = 588 TranslateNativeToVulkanTransform(transform_hint); 589 590 // On Android, window composition is a WindowManager property, not something 591 // associated with the bufferqueue. It can't be changed from here. 592 capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; 593 594 // TODO(jessehall): I think these are right, but haven't thought hard about 595 // it. Do we need to query the driver for support of any of these? 596 // Currently not included: 597 // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not 598 // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not 599 capabilities->supportedUsageFlags = 600 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | 601 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | 602 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 603 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 604 605 return VK_SUCCESS; 606 } 607 608 VKAPI_ATTR 609 VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, 610 VkSurfaceKHR surface_handle, 611 uint32_t* count, 612 VkSurfaceFormatKHR* formats) { 613 const InstanceData& instance_data = GetData(pdev); 614 615 // TODO(jessehall): Fill out the set of supported formats. Longer term, add 616 // a new gralloc method to query whether a (format, usage) pair is 617 // supported, and check that for each gralloc format that corresponds to a 618 // Vulkan format. Shorter term, just add a few more formats to the ones 619 // hardcoded below. 620 621 const VkSurfaceFormatKHR kFormats[] = { 622 {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}, 623 {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}, 624 {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}, 625 }; 626 const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]); 627 uint32_t total_num_formats = kNumFormats; 628 629 bool wide_color_support = false; 630 Surface& surface = *SurfaceFromHandle(surface_handle); 631 int err = native_window_get_wide_color_support(surface.window.get(), 632 &wide_color_support); 633 if (err) { 634 // Not allowed to return a more sensible error code, so do this 635 return VK_ERROR_OUT_OF_HOST_MEMORY; 636 } 637 ALOGV("wide_color_support is: %d", wide_color_support); 638 wide_color_support = 639 wide_color_support && 640 instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace); 641 642 const VkSurfaceFormatKHR kWideColorFormats[] = { 643 {VK_FORMAT_R8G8B8A8_UNORM, 644 VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT}, 645 {VK_FORMAT_R8G8B8A8_SRGB, 646 VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT}, 647 }; 648 const uint32_t kNumWideColorFormats = 649 sizeof(kWideColorFormats) / sizeof(kWideColorFormats[0]); 650 if (wide_color_support) { 651 total_num_formats += kNumWideColorFormats; 652 } 653 654 VkResult result = VK_SUCCESS; 655 if (formats) { 656 uint32_t out_count = 0; 657 uint32_t transfer_count = 0; 658 if (*count < total_num_formats) 659 result = VK_INCOMPLETE; 660 transfer_count = std::min(*count, kNumFormats); 661 std::copy(kFormats, kFormats + transfer_count, formats); 662 out_count += transfer_count; 663 if (wide_color_support) { 664 transfer_count = std::min(*count - out_count, kNumWideColorFormats); 665 std::copy(kWideColorFormats, kWideColorFormats + transfer_count, 666 formats + out_count); 667 out_count += transfer_count; 668 } 669 *count = out_count; 670 } else { 671 *count = total_num_formats; 672 } 673 return result; 674 } 675 676 VKAPI_ATTR 677 VkResult GetPhysicalDeviceSurfaceCapabilities2KHR( 678 VkPhysicalDevice physicalDevice, 679 const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, 680 VkSurfaceCapabilities2KHR* pSurfaceCapabilities) { 681 VkResult result = GetPhysicalDeviceSurfaceCapabilitiesKHR( 682 physicalDevice, pSurfaceInfo->surface, 683 &pSurfaceCapabilities->surfaceCapabilities); 684 685 VkSurfaceCapabilities2KHR* caps = pSurfaceCapabilities; 686 while (caps->pNext) { 687 caps = reinterpret_cast<VkSurfaceCapabilities2KHR*>(caps->pNext); 688 689 switch (caps->sType) { 690 case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: { 691 VkSharedPresentSurfaceCapabilitiesKHR* shared_caps = 692 reinterpret_cast<VkSharedPresentSurfaceCapabilitiesKHR*>( 693 caps); 694 // Claim same set of usage flags are supported for 695 // shared present modes as for other modes. 696 shared_caps->sharedPresentSupportedUsageFlags = 697 pSurfaceCapabilities->surfaceCapabilities 698 .supportedUsageFlags; 699 } break; 700 701 default: 702 // Ignore all other extension structs 703 break; 704 } 705 } 706 707 return result; 708 } 709 710 VKAPI_ATTR 711 VkResult GetPhysicalDeviceSurfaceFormats2KHR( 712 VkPhysicalDevice physicalDevice, 713 const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, 714 uint32_t* pSurfaceFormatCount, 715 VkSurfaceFormat2KHR* pSurfaceFormats) { 716 if (!pSurfaceFormats) { 717 return GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, 718 pSurfaceInfo->surface, 719 pSurfaceFormatCount, nullptr); 720 } else { 721 // temp vector for forwarding; we'll marshal it into the pSurfaceFormats 722 // after the call. 723 android::Vector<VkSurfaceFormatKHR> surface_formats; 724 surface_formats.resize(*pSurfaceFormatCount); 725 VkResult result = GetPhysicalDeviceSurfaceFormatsKHR( 726 physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount, 727 &surface_formats.editItemAt(0)); 728 729 if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 730 // marshal results individually due to stride difference. 731 // completely ignore any chained extension structs. 732 uint32_t formats_to_marshal = *pSurfaceFormatCount; 733 for (uint32_t i = 0u; i < formats_to_marshal; i++) { 734 pSurfaceFormats[i].surfaceFormat = surface_formats[i]; 735 } 736 } 737 738 return result; 739 } 740 } 741 742 VKAPI_ATTR 743 VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, 744 VkSurfaceKHR /*surface*/, 745 uint32_t* count, 746 VkPresentModeKHR* modes) { 747 android::Vector<VkPresentModeKHR> present_modes; 748 present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR); 749 present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR); 750 751 VkPhysicalDevicePresentationPropertiesANDROID present_properties; 752 if (QueryPresentationProperties(pdev, &present_properties)) { 753 if (present_properties.sharedImage) { 754 present_modes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR); 755 present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR); 756 } 757 } 758 759 uint32_t num_modes = uint32_t(present_modes.size()); 760 761 VkResult result = VK_SUCCESS; 762 if (modes) { 763 if (*count < num_modes) 764 result = VK_INCOMPLETE; 765 *count = std::min(*count, num_modes); 766 std::copy(present_modes.begin(), present_modes.begin() + int(*count), modes); 767 } else { 768 *count = num_modes; 769 } 770 return result; 771 } 772 773 VKAPI_ATTR 774 VkResult CreateSwapchainKHR(VkDevice device, 775 const VkSwapchainCreateInfoKHR* create_info, 776 const VkAllocationCallbacks* allocator, 777 VkSwapchainKHR* swapchain_handle) { 778 int err; 779 VkResult result = VK_SUCCESS; 780 781 ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64 782 " minImageCount=%u imageFormat=%u imageColorSpace=%u" 783 " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u" 784 " oldSwapchain=0x%" PRIx64, 785 reinterpret_cast<uint64_t>(create_info->surface), 786 create_info->minImageCount, create_info->imageFormat, 787 create_info->imageColorSpace, create_info->imageExtent.width, 788 create_info->imageExtent.height, create_info->imageUsage, 789 create_info->preTransform, create_info->presentMode, 790 reinterpret_cast<uint64_t>(create_info->oldSwapchain)); 791 792 if (!allocator) 793 allocator = &GetData(device).allocator; 794 795 android_pixel_format native_pixel_format = 796 GetNativePixelFormat(create_info->imageFormat); 797 android_dataspace native_dataspace = 798 GetNativeDataspace(create_info->imageColorSpace); 799 if (native_dataspace == HAL_DATASPACE_UNKNOWN) { 800 ALOGE( 801 "CreateSwapchainKHR(VkSwapchainCreateInfoKHR.imageColorSpace = %d) " 802 "failed: Unsupported color space", 803 create_info->imageColorSpace); 804 return VK_ERROR_INITIALIZATION_FAILED; 805 } 806 807 ALOGV_IF(create_info->imageArrayLayers != 1, 808 "swapchain imageArrayLayers=%u not supported", 809 create_info->imageArrayLayers); 810 ALOGV_IF((create_info->preTransform & ~kSupportedTransforms) != 0, 811 "swapchain preTransform=%#x not supported", 812 create_info->preTransform); 813 ALOGV_IF(!(create_info->presentMode == VK_PRESENT_MODE_FIFO_KHR || 814 create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR || 815 create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR || 816 create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR), 817 "swapchain presentMode=%u not supported", 818 create_info->presentMode); 819 820 Surface& surface = *SurfaceFromHandle(create_info->surface); 821 822 if (surface.swapchain_handle != create_info->oldSwapchain) { 823 ALOGV("Can't create a swapchain for VkSurfaceKHR 0x%" PRIx64 824 " because it already has active swapchain 0x%" PRIx64 825 " but VkSwapchainCreateInfo::oldSwapchain=0x%" PRIx64, 826 reinterpret_cast<uint64_t>(create_info->surface), 827 reinterpret_cast<uint64_t>(surface.swapchain_handle), 828 reinterpret_cast<uint64_t>(create_info->oldSwapchain)); 829 return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR; 830 } 831 if (create_info->oldSwapchain != VK_NULL_HANDLE) 832 OrphanSwapchain(device, SwapchainFromHandle(create_info->oldSwapchain)); 833 834 // -- Reset the native window -- 835 // The native window might have been used previously, and had its properties 836 // changed from defaults. That will affect the answer we get for queries 837 // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we 838 // attempt such queries. 839 840 // The native window only allows dequeueing all buffers before any have 841 // been queued, since after that point at least one is assumed to be in 842 // non-FREE state at any given time. Disconnecting and re-connecting 843 // orphans the previous buffers, getting us back to the state where we can 844 // dequeue all buffers. 845 err = native_window_api_disconnect(surface.window.get(), 846 NATIVE_WINDOW_API_EGL); 847 ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)", 848 strerror(-err), err); 849 err = 850 native_window_api_connect(surface.window.get(), NATIVE_WINDOW_API_EGL); 851 ALOGW_IF(err != 0, "native_window_api_connect failed: %s (%d)", 852 strerror(-err), err); 853 854 err = native_window_set_buffer_count(surface.window.get(), 0); 855 if (err != 0) { 856 ALOGE("native_window_set_buffer_count(0) failed: %s (%d)", 857 strerror(-err), err); 858 return VK_ERROR_SURFACE_LOST_KHR; 859 } 860 861 int swap_interval = 862 create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1; 863 err = surface.window->setSwapInterval(surface.window.get(), swap_interval); 864 if (err != 0) { 865 // TODO(jessehall): Improve error reporting. Can we enumerate possible 866 // errors and translate them to valid Vulkan result codes? 867 ALOGE("native_window->setSwapInterval(1) failed: %s (%d)", 868 strerror(-err), err); 869 return VK_ERROR_SURFACE_LOST_KHR; 870 } 871 872 err = native_window_set_shared_buffer_mode(surface.window.get(), false); 873 if (err != 0) { 874 ALOGE("native_window_set_shared_buffer_mode(false) failed: %s (%d)", 875 strerror(-err), err); 876 return VK_ERROR_SURFACE_LOST_KHR; 877 } 878 879 err = native_window_set_auto_refresh(surface.window.get(), false); 880 if (err != 0) { 881 ALOGE("native_window_set_auto_refresh(false) failed: %s (%d)", 882 strerror(-err), err); 883 return VK_ERROR_SURFACE_LOST_KHR; 884 } 885 886 // -- Configure the native window -- 887 888 const auto& dispatch = GetData(device).driver; 889 890 err = native_window_set_buffers_format(surface.window.get(), 891 native_pixel_format); 892 if (err != 0) { 893 // TODO(jessehall): Improve error reporting. Can we enumerate possible 894 // errors and translate them to valid Vulkan result codes? 895 ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)", 896 native_pixel_format, strerror(-err), err); 897 return VK_ERROR_SURFACE_LOST_KHR; 898 } 899 err = native_window_set_buffers_data_space(surface.window.get(), 900 native_dataspace); 901 if (err != 0) { 902 // TODO(jessehall): Improve error reporting. Can we enumerate possible 903 // errors and translate them to valid Vulkan result codes? 904 ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)", 905 native_dataspace, strerror(-err), err); 906 return VK_ERROR_SURFACE_LOST_KHR; 907 } 908 909 err = native_window_set_buffers_dimensions( 910 surface.window.get(), static_cast<int>(create_info->imageExtent.width), 911 static_cast<int>(create_info->imageExtent.height)); 912 if (err != 0) { 913 // TODO(jessehall): Improve error reporting. Can we enumerate possible 914 // errors and translate them to valid Vulkan result codes? 915 ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)", 916 create_info->imageExtent.width, create_info->imageExtent.height, 917 strerror(-err), err); 918 return VK_ERROR_SURFACE_LOST_KHR; 919 } 920 921 // VkSwapchainCreateInfo::preTransform indicates the transformation the app 922 // applied during rendering. native_window_set_transform() expects the 923 // inverse: the transform the app is requesting that the compositor perform 924 // during composition. With native windows, pre-transform works by rendering 925 // with the same transform the compositor is applying (as in Vulkan), but 926 // then requesting the inverse transform, so that when the compositor does 927 // it's job the two transforms cancel each other out and the compositor ends 928 // up applying an identity transform to the app's buffer. 929 err = native_window_set_buffers_transform( 930 surface.window.get(), 931 InvertTransformToNative(create_info->preTransform)); 932 if (err != 0) { 933 // TODO(jessehall): Improve error reporting. Can we enumerate possible 934 // errors and translate them to valid Vulkan result codes? 935 ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)", 936 InvertTransformToNative(create_info->preTransform), 937 strerror(-err), err); 938 return VK_ERROR_SURFACE_LOST_KHR; 939 } 940 941 err = native_window_set_scaling_mode( 942 surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 943 if (err != 0) { 944 // TODO(jessehall): Improve error reporting. Can we enumerate possible 945 // errors and translate them to valid Vulkan result codes? 946 ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)", 947 strerror(-err), err); 948 return VK_ERROR_SURFACE_LOST_KHR; 949 } 950 951 VkSwapchainImageUsageFlagsANDROID swapchain_image_usage = 0; 952 if (create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR || 953 create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) { 954 swapchain_image_usage |= VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID; 955 err = native_window_set_shared_buffer_mode(surface.window.get(), true); 956 if (err != 0) { 957 ALOGE("native_window_set_shared_buffer_mode failed: %s (%d)", strerror(-err), err); 958 return VK_ERROR_SURFACE_LOST_KHR; 959 } 960 } 961 962 if (create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) { 963 err = native_window_set_auto_refresh(surface.window.get(), true); 964 if (err != 0) { 965 ALOGE("native_window_set_auto_refresh failed: %s (%d)", strerror(-err), err); 966 return VK_ERROR_SURFACE_LOST_KHR; 967 } 968 } 969 970 int query_value; 971 err = surface.window->query(surface.window.get(), 972 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 973 &query_value); 974 if (err != 0 || query_value < 0) { 975 // TODO(jessehall): Improve error reporting. Can we enumerate possible 976 // errors and translate them to valid Vulkan result codes? 977 ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, 978 query_value); 979 return VK_ERROR_SURFACE_LOST_KHR; 980 } 981 uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value); 982 uint32_t num_images = 983 (create_info->minImageCount - 1) + min_undequeued_buffers; 984 985 // Lower layer insists that we have at least two buffers. This is wasteful 986 // and we'd like to relax it in the shared case, but not all the pieces are 987 // in place for that to work yet. Note we only lie to the lower layer-- we 988 // don't want to give the app back a swapchain with extra images (which they 989 // can't actually use!). 990 err = native_window_set_buffer_count(surface.window.get(), std::max(2u, num_images)); 991 if (err != 0) { 992 // TODO(jessehall): Improve error reporting. Can we enumerate possible 993 // errors and translate them to valid Vulkan result codes? 994 ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images, 995 strerror(-err), err); 996 return VK_ERROR_SURFACE_LOST_KHR; 997 } 998 999 int gralloc_usage = 0; 1000 if (dispatch.GetSwapchainGrallocUsage2ANDROID) { 1001 uint64_t consumer_usage, producer_usage; 1002 result = dispatch.GetSwapchainGrallocUsage2ANDROID( 1003 device, create_info->imageFormat, create_info->imageUsage, 1004 swapchain_image_usage, &consumer_usage, &producer_usage); 1005 if (result != VK_SUCCESS) { 1006 ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result); 1007 return VK_ERROR_SURFACE_LOST_KHR; 1008 } 1009 gralloc_usage = 1010 android_convertGralloc1To0Usage(producer_usage, consumer_usage); 1011 } else if (dispatch.GetSwapchainGrallocUsageANDROID) { 1012 result = dispatch.GetSwapchainGrallocUsageANDROID( 1013 device, create_info->imageFormat, create_info->imageUsage, 1014 &gralloc_usage); 1015 if (result != VK_SUCCESS) { 1016 ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result); 1017 return VK_ERROR_SURFACE_LOST_KHR; 1018 } 1019 } 1020 err = native_window_set_usage(surface.window.get(), uint64_t(gralloc_usage)); 1021 if (err != 0) { 1022 // TODO(jessehall): Improve error reporting. Can we enumerate possible 1023 // errors and translate them to valid Vulkan result codes? 1024 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err); 1025 return VK_ERROR_SURFACE_LOST_KHR; 1026 } 1027 1028 // -- Allocate our Swapchain object -- 1029 // After this point, we must deallocate the swapchain on error. 1030 1031 void* mem = allocator->pfnAllocation(allocator->pUserData, 1032 sizeof(Swapchain), alignof(Swapchain), 1033 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1034 if (!mem) 1035 return VK_ERROR_OUT_OF_HOST_MEMORY; 1036 Swapchain* swapchain = 1037 new (mem) Swapchain(surface, num_images, create_info->presentMode); 1038 1039 // -- Dequeue all buffers and create a VkImage for each -- 1040 // Any failures during or after this must cancel the dequeued buffers. 1041 1042 VkSwapchainImageCreateInfoANDROID swapchain_image_create = { 1043 #pragma clang diagnostic push 1044 #pragma clang diagnostic ignored "-Wold-style-cast" 1045 .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID, 1046 #pragma clang diagnostic pop 1047 .pNext = nullptr, 1048 .usage = swapchain_image_usage, 1049 }; 1050 VkNativeBufferANDROID image_native_buffer = { 1051 #pragma clang diagnostic push 1052 #pragma clang diagnostic ignored "-Wold-style-cast" 1053 .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID, 1054 #pragma clang diagnostic pop 1055 .pNext = &swapchain_image_create, 1056 }; 1057 VkImageCreateInfo image_create = { 1058 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 1059 .pNext = &image_native_buffer, 1060 .imageType = VK_IMAGE_TYPE_2D, 1061 .format = create_info->imageFormat, 1062 .extent = {0, 0, 1}, 1063 .mipLevels = 1, 1064 .arrayLayers = 1, 1065 .samples = VK_SAMPLE_COUNT_1_BIT, 1066 .tiling = VK_IMAGE_TILING_OPTIMAL, 1067 .usage = create_info->imageUsage, 1068 .flags = 0, 1069 .sharingMode = create_info->imageSharingMode, 1070 .queueFamilyIndexCount = create_info->queueFamilyIndexCount, 1071 .pQueueFamilyIndices = create_info->pQueueFamilyIndices, 1072 }; 1073 1074 for (uint32_t i = 0; i < num_images; i++) { 1075 Swapchain::Image& img = swapchain->images[i]; 1076 1077 ANativeWindowBuffer* buffer; 1078 err = surface.window->dequeueBuffer(surface.window.get(), &buffer, 1079 &img.dequeue_fence); 1080 if (err != 0) { 1081 // TODO(jessehall): Improve error reporting. Can we enumerate 1082 // possible errors and translate them to valid Vulkan result codes? 1083 ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err); 1084 result = VK_ERROR_SURFACE_LOST_KHR; 1085 break; 1086 } 1087 img.buffer = buffer; 1088 img.dequeued = true; 1089 1090 image_create.extent = 1091 VkExtent3D{static_cast<uint32_t>(img.buffer->width), 1092 static_cast<uint32_t>(img.buffer->height), 1093 1}; 1094 image_native_buffer.handle = img.buffer->handle; 1095 image_native_buffer.stride = img.buffer->stride; 1096 image_native_buffer.format = img.buffer->format; 1097 image_native_buffer.usage = int(img.buffer->usage); 1098 android_convertGralloc0To1Usage(int(img.buffer->usage), 1099 &image_native_buffer.usage2.producer, 1100 &image_native_buffer.usage2.consumer); 1101 1102 result = 1103 dispatch.CreateImage(device, &image_create, nullptr, &img.image); 1104 if (result != VK_SUCCESS) { 1105 ALOGD("vkCreateImage w/ native buffer failed: %u", result); 1106 break; 1107 } 1108 } 1109 1110 // -- Cancel all buffers, returning them to the queue -- 1111 // If an error occurred before, also destroy the VkImage and release the 1112 // buffer reference. Otherwise, we retain a strong reference to the buffer. 1113 // 1114 // TODO(jessehall): The error path here is the same as DestroySwapchain, 1115 // but not the non-error path. Should refactor/unify. 1116 if (!swapchain->shared) { 1117 for (uint32_t i = 0; i < num_images; i++) { 1118 Swapchain::Image& img = swapchain->images[i]; 1119 if (img.dequeued) { 1120 surface.window->cancelBuffer(surface.window.get(), img.buffer.get(), 1121 img.dequeue_fence); 1122 img.dequeue_fence = -1; 1123 img.dequeued = false; 1124 } 1125 if (result != VK_SUCCESS) { 1126 if (img.image) 1127 dispatch.DestroyImage(device, img.image, nullptr); 1128 } 1129 } 1130 } 1131 1132 if (result != VK_SUCCESS) { 1133 swapchain->~Swapchain(); 1134 allocator->pfnFree(allocator->pUserData, swapchain); 1135 return result; 1136 } 1137 1138 surface.swapchain_handle = HandleFromSwapchain(swapchain); 1139 *swapchain_handle = surface.swapchain_handle; 1140 return VK_SUCCESS; 1141 } 1142 1143 VKAPI_ATTR 1144 void DestroySwapchainKHR(VkDevice device, 1145 VkSwapchainKHR swapchain_handle, 1146 const VkAllocationCallbacks* allocator) { 1147 const auto& dispatch = GetData(device).driver; 1148 Swapchain* swapchain = SwapchainFromHandle(swapchain_handle); 1149 if (!swapchain) 1150 return; 1151 bool active = swapchain->surface.swapchain_handle == swapchain_handle; 1152 ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr; 1153 1154 if (swapchain->frame_timestamps_enabled) { 1155 native_window_enable_frame_timestamps(window, false); 1156 } 1157 for (uint32_t i = 0; i < swapchain->num_images; i++) 1158 ReleaseSwapchainImage(device, window, -1, swapchain->images[i]); 1159 if (active) 1160 swapchain->surface.swapchain_handle = VK_NULL_HANDLE; 1161 if (!allocator) 1162 allocator = &GetData(device).allocator; 1163 swapchain->~Swapchain(); 1164 allocator->pfnFree(allocator->pUserData, swapchain); 1165 } 1166 1167 VKAPI_ATTR 1168 VkResult GetSwapchainImagesKHR(VkDevice, 1169 VkSwapchainKHR swapchain_handle, 1170 uint32_t* count, 1171 VkImage* images) { 1172 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); 1173 ALOGW_IF(swapchain.surface.swapchain_handle != swapchain_handle, 1174 "getting images for non-active swapchain 0x%" PRIx64 1175 "; only dequeued image handles are valid", 1176 reinterpret_cast<uint64_t>(swapchain_handle)); 1177 VkResult result = VK_SUCCESS; 1178 if (images) { 1179 uint32_t n = swapchain.num_images; 1180 if (*count < swapchain.num_images) { 1181 n = *count; 1182 result = VK_INCOMPLETE; 1183 } 1184 for (uint32_t i = 0; i < n; i++) 1185 images[i] = swapchain.images[i].image; 1186 *count = n; 1187 } else { 1188 *count = swapchain.num_images; 1189 } 1190 return result; 1191 } 1192 1193 VKAPI_ATTR 1194 VkResult AcquireNextImageKHR(VkDevice device, 1195 VkSwapchainKHR swapchain_handle, 1196 uint64_t timeout, 1197 VkSemaphore semaphore, 1198 VkFence vk_fence, 1199 uint32_t* image_index) { 1200 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); 1201 ANativeWindow* window = swapchain.surface.window.get(); 1202 VkResult result; 1203 int err; 1204 1205 if (swapchain.surface.swapchain_handle != swapchain_handle) 1206 return VK_ERROR_OUT_OF_DATE_KHR; 1207 1208 ALOGW_IF( 1209 timeout != UINT64_MAX, 1210 "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented"); 1211 1212 if (swapchain.shared) { 1213 // In shared mode, we keep the buffer dequeued all the time, so we don't 1214 // want to dequeue a buffer here. Instead, just ask the driver to ensure 1215 // the semaphore and fence passed to us will be signalled. 1216 *image_index = 0; 1217 result = GetData(device).driver.AcquireImageANDROID( 1218 device, swapchain.images[*image_index].image, -1, semaphore, vk_fence); 1219 return result; 1220 } 1221 1222 ANativeWindowBuffer* buffer; 1223 int fence_fd; 1224 err = window->dequeueBuffer(window, &buffer, &fence_fd); 1225 if (err != 0) { 1226 // TODO(jessehall): Improve error reporting. Can we enumerate possible 1227 // errors and translate them to valid Vulkan result codes? 1228 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err); 1229 return VK_ERROR_SURFACE_LOST_KHR; 1230 } 1231 1232 uint32_t idx; 1233 for (idx = 0; idx < swapchain.num_images; idx++) { 1234 if (swapchain.images[idx].buffer.get() == buffer) { 1235 swapchain.images[idx].dequeued = true; 1236 swapchain.images[idx].dequeue_fence = fence_fd; 1237 break; 1238 } 1239 } 1240 if (idx == swapchain.num_images) { 1241 ALOGE("dequeueBuffer returned unrecognized buffer"); 1242 window->cancelBuffer(window, buffer, fence_fd); 1243 return VK_ERROR_OUT_OF_DATE_KHR; 1244 } 1245 1246 int fence_clone = -1; 1247 if (fence_fd != -1) { 1248 fence_clone = dup(fence_fd); 1249 if (fence_clone == -1) { 1250 ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", 1251 strerror(errno), errno); 1252 sync_wait(fence_fd, -1 /* forever */); 1253 } 1254 } 1255 1256 result = GetData(device).driver.AcquireImageANDROID( 1257 device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence); 1258 if (result != VK_SUCCESS) { 1259 // NOTE: we're relying on AcquireImageANDROID to close fence_clone, 1260 // even if the call fails. We could close it ourselves on failure, but 1261 // that would create a race condition if the driver closes it on a 1262 // failure path: some other thread might create an fd with the same 1263 // number between the time the driver closes it and the time we close 1264 // it. We must assume one of: the driver *always* closes it even on 1265 // failure, or *never* closes it on failure. 1266 window->cancelBuffer(window, buffer, fence_fd); 1267 swapchain.images[idx].dequeued = false; 1268 swapchain.images[idx].dequeue_fence = -1; 1269 return result; 1270 } 1271 1272 *image_index = idx; 1273 return VK_SUCCESS; 1274 } 1275 1276 static VkResult WorstPresentResult(VkResult a, VkResult b) { 1277 // See the error ranking for vkQueuePresentKHR at the end of section 29.6 1278 // (in spec version 1.0.14). 1279 static const VkResult kWorstToBest[] = { 1280 VK_ERROR_DEVICE_LOST, 1281 VK_ERROR_SURFACE_LOST_KHR, 1282 VK_ERROR_OUT_OF_DATE_KHR, 1283 VK_ERROR_OUT_OF_DEVICE_MEMORY, 1284 VK_ERROR_OUT_OF_HOST_MEMORY, 1285 VK_SUBOPTIMAL_KHR, 1286 }; 1287 for (auto result : kWorstToBest) { 1288 if (a == result || b == result) 1289 return result; 1290 } 1291 ALOG_ASSERT(a == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", a); 1292 ALOG_ASSERT(b == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", b); 1293 return a != VK_SUCCESS ? a : b; 1294 } 1295 1296 VKAPI_ATTR 1297 VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { 1298 ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 1299 "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d", 1300 present_info->sType); 1301 1302 VkDevice device = GetData(queue).driver_device; 1303 const auto& dispatch = GetData(queue).driver; 1304 VkResult final_result = VK_SUCCESS; 1305 1306 // Look at the pNext chain for supported extension structs: 1307 const VkPresentRegionsKHR* present_regions = nullptr; 1308 const VkPresentTimesInfoGOOGLE* present_times = nullptr; 1309 const VkPresentRegionsKHR* next = 1310 reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext); 1311 while (next) { 1312 switch (next->sType) { 1313 case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR: 1314 present_regions = next; 1315 break; 1316 case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE: 1317 present_times = 1318 reinterpret_cast<const VkPresentTimesInfoGOOGLE*>(next); 1319 break; 1320 default: 1321 ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x", 1322 next->sType); 1323 break; 1324 } 1325 next = reinterpret_cast<const VkPresentRegionsKHR*>(next->pNext); 1326 } 1327 ALOGV_IF( 1328 present_regions && 1329 present_regions->swapchainCount != present_info->swapchainCount, 1330 "VkPresentRegions::swapchainCount != VkPresentInfo::swapchainCount"); 1331 ALOGV_IF(present_times && 1332 present_times->swapchainCount != present_info->swapchainCount, 1333 "VkPresentTimesInfoGOOGLE::swapchainCount != " 1334 "VkPresentInfo::swapchainCount"); 1335 const VkPresentRegionKHR* regions = 1336 (present_regions) ? present_regions->pRegions : nullptr; 1337 const VkPresentTimeGOOGLE* times = 1338 (present_times) ? present_times->pTimes : nullptr; 1339 const VkAllocationCallbacks* allocator = &GetData(device).allocator; 1340 android_native_rect_t* rects = nullptr; 1341 uint32_t nrects = 0; 1342 1343 for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) { 1344 Swapchain& swapchain = 1345 *SwapchainFromHandle(present_info->pSwapchains[sc]); 1346 uint32_t image_idx = present_info->pImageIndices[sc]; 1347 Swapchain::Image& img = swapchain.images[image_idx]; 1348 const VkPresentRegionKHR* region = 1349 (regions && !swapchain.mailbox_mode) ? ®ions[sc] : nullptr; 1350 const VkPresentTimeGOOGLE* time = (times) ? ×[sc] : nullptr; 1351 VkResult swapchain_result = VK_SUCCESS; 1352 VkResult result; 1353 int err; 1354 1355 int fence = -1; 1356 result = dispatch.QueueSignalReleaseImageANDROID( 1357 queue, present_info->waitSemaphoreCount, 1358 present_info->pWaitSemaphores, img.image, &fence); 1359 if (result != VK_SUCCESS) { 1360 ALOGE("QueueSignalReleaseImageANDROID failed: %d", result); 1361 swapchain_result = result; 1362 } 1363 1364 if (swapchain.surface.swapchain_handle == 1365 present_info->pSwapchains[sc]) { 1366 ANativeWindow* window = swapchain.surface.window.get(); 1367 if (swapchain_result == VK_SUCCESS) { 1368 if (region) { 1369 // Process the incremental-present hint for this swapchain: 1370 uint32_t rcount = region->rectangleCount; 1371 if (rcount > nrects) { 1372 android_native_rect_t* new_rects = 1373 static_cast<android_native_rect_t*>( 1374 allocator->pfnReallocation( 1375 allocator->pUserData, rects, 1376 sizeof(android_native_rect_t) * rcount, 1377 alignof(android_native_rect_t), 1378 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); 1379 if (new_rects) { 1380 rects = new_rects; 1381 nrects = rcount; 1382 } else { 1383 rcount = 0; // Ignore the hint for this swapchain 1384 } 1385 } 1386 for (uint32_t r = 0; r < rcount; ++r) { 1387 if (region->pRectangles[r].layer > 0) { 1388 ALOGV( 1389 "vkQueuePresentKHR ignoring invalid layer " 1390 "(%u); using layer 0 instead", 1391 region->pRectangles[r].layer); 1392 } 1393 int x = region->pRectangles[r].offset.x; 1394 int y = region->pRectangles[r].offset.y; 1395 int width = static_cast<int>( 1396 region->pRectangles[r].extent.width); 1397 int height = static_cast<int>( 1398 region->pRectangles[r].extent.height); 1399 android_native_rect_t* cur_rect = &rects[r]; 1400 cur_rect->left = x; 1401 cur_rect->top = y + height; 1402 cur_rect->right = x + width; 1403 cur_rect->bottom = y; 1404 } 1405 native_window_set_surface_damage(window, rects, rcount); 1406 } 1407 if (time) { 1408 if (!swapchain.frame_timestamps_enabled) { 1409 ALOGV( 1410 "Calling " 1411 "native_window_enable_frame_timestamps(true)"); 1412 native_window_enable_frame_timestamps(window, true); 1413 swapchain.frame_timestamps_enabled = true; 1414 } 1415 1416 // Record the nativeFrameId so it can be later correlated to 1417 // this present. 1418 uint64_t nativeFrameId = 0; 1419 err = native_window_get_next_frame_id( 1420 window, &nativeFrameId); 1421 if (err != android::NO_ERROR) { 1422 ALOGE("Failed to get next native frame ID."); 1423 } 1424 1425 // Add a new timing record with the user's presentID and 1426 // the nativeFrameId. 1427 swapchain.timing.push_back(TimingInfo(time, nativeFrameId)); 1428 while (swapchain.timing.size() > MAX_TIMING_INFOS) { 1429 swapchain.timing.removeAt(0); 1430 } 1431 if (time->desiredPresentTime) { 1432 // Set the desiredPresentTime: 1433 ALOGV( 1434 "Calling " 1435 "native_window_set_buffers_timestamp(%" PRId64 ")", 1436 time->desiredPresentTime); 1437 native_window_set_buffers_timestamp( 1438 window, 1439 static_cast<int64_t>(time->desiredPresentTime)); 1440 } 1441 } 1442 1443 err = window->queueBuffer(window, img.buffer.get(), fence); 1444 // queueBuffer always closes fence, even on error 1445 if (err != 0) { 1446 // TODO(jessehall): What now? We should probably cancel the 1447 // buffer, I guess? 1448 ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err); 1449 swapchain_result = WorstPresentResult( 1450 swapchain_result, VK_ERROR_OUT_OF_DATE_KHR); 1451 } 1452 if (img.dequeue_fence >= 0) { 1453 close(img.dequeue_fence); 1454 img.dequeue_fence = -1; 1455 } 1456 img.dequeued = false; 1457 1458 // If the swapchain is in shared mode, immediately dequeue the 1459 // buffer so it can be presented again without an intervening 1460 // call to AcquireNextImageKHR. We expect to get the same buffer 1461 // back from every call to dequeueBuffer in this mode. 1462 if (swapchain.shared && swapchain_result == VK_SUCCESS) { 1463 ANativeWindowBuffer* buffer; 1464 int fence_fd; 1465 err = window->dequeueBuffer(window, &buffer, &fence_fd); 1466 if (err != 0) { 1467 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err); 1468 swapchain_result = WorstPresentResult(swapchain_result, 1469 VK_ERROR_SURFACE_LOST_KHR); 1470 } 1471 else if (img.buffer != buffer) { 1472 ALOGE("got wrong image back for shared swapchain"); 1473 swapchain_result = WorstPresentResult(swapchain_result, 1474 VK_ERROR_SURFACE_LOST_KHR); 1475 } 1476 else { 1477 img.dequeue_fence = fence_fd; 1478 img.dequeued = true; 1479 } 1480 } 1481 } 1482 if (swapchain_result != VK_SUCCESS) { 1483 ReleaseSwapchainImage(device, window, fence, img); 1484 OrphanSwapchain(device, &swapchain); 1485 } 1486 } else { 1487 ReleaseSwapchainImage(device, nullptr, fence, img); 1488 swapchain_result = VK_ERROR_OUT_OF_DATE_KHR; 1489 } 1490 1491 if (present_info->pResults) 1492 present_info->pResults[sc] = swapchain_result; 1493 1494 if (swapchain_result != final_result) 1495 final_result = WorstPresentResult(final_result, swapchain_result); 1496 } 1497 if (rects) { 1498 allocator->pfnFree(allocator->pUserData, rects); 1499 } 1500 1501 return final_result; 1502 } 1503 1504 VKAPI_ATTR 1505 VkResult GetRefreshCycleDurationGOOGLE( 1506 VkDevice, 1507 VkSwapchainKHR swapchain_handle, 1508 VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) { 1509 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); 1510 VkResult result = VK_SUCCESS; 1511 1512 pDisplayTimingProperties->refreshDuration = 1513 static_cast<uint64_t>(swapchain.refresh_duration); 1514 1515 return result; 1516 } 1517 1518 VKAPI_ATTR 1519 VkResult GetPastPresentationTimingGOOGLE( 1520 VkDevice, 1521 VkSwapchainKHR swapchain_handle, 1522 uint32_t* count, 1523 VkPastPresentationTimingGOOGLE* timings) { 1524 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); 1525 ANativeWindow* window = swapchain.surface.window.get(); 1526 VkResult result = VK_SUCCESS; 1527 1528 if (!swapchain.frame_timestamps_enabled) { 1529 ALOGV("Calling native_window_enable_frame_timestamps(true)"); 1530 native_window_enable_frame_timestamps(window, true); 1531 swapchain.frame_timestamps_enabled = true; 1532 } 1533 1534 if (timings) { 1535 // TODO(ianelliott): plumb return value (e.g. VK_INCOMPLETE) 1536 copy_ready_timings(swapchain, count, timings); 1537 } else { 1538 *count = get_num_ready_timings(swapchain); 1539 } 1540 1541 return result; 1542 } 1543 1544 VKAPI_ATTR 1545 VkResult GetSwapchainStatusKHR( 1546 VkDevice, 1547 VkSwapchainKHR swapchain_handle) { 1548 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); 1549 VkResult result = VK_SUCCESS; 1550 1551 if (swapchain.surface.swapchain_handle != swapchain_handle) { 1552 return VK_ERROR_OUT_OF_DATE_KHR; 1553 } 1554 1555 // TODO(chrisforbes): Implement this function properly 1556 1557 return result; 1558 } 1559 1560 VKAPI_ATTR void SetHdrMetadataEXT( 1561 VkDevice device, 1562 uint32_t swapchainCount, 1563 const VkSwapchainKHR* pSwapchains, 1564 const VkHdrMetadataEXT* pHdrMetadataEXTs) { 1565 // TODO: courtneygo: implement actual function 1566 (void)device; 1567 (void)swapchainCount; 1568 (void)pSwapchains; 1569 (void)pHdrMetadataEXTs; 1570 return; 1571 } 1572 1573 } // namespace driver 1574 } // namespace vulkan 1575