Initial implementation of VK_KHR_incremental_present.
Test: Manually tested with the Vulkan cube demo, examining logcat output to
ensure that the VkRectLayerKHR data made it all the way down to HWC2.
Change-Id: I6085acfab1b9db80a4a930dc2c0008b3a3fc0277
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 63c597c..7e90503 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -860,17 +860,43 @@
ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
"vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
present_info->sType);
- ALOGV_IF(present_info->pNext, "VkPresentInfo::pNext != NULL");
VkDevice device = GetData(queue).driver_device;
const auto& dispatch = GetData(queue).driver;
VkResult final_result = VK_SUCCESS;
+ // Look at the pNext chain for supported extension structs:
+ const VkPresentRegionsKHR* present_regions = NULL;
+ const VkPresentRegionsKHR* next =
+ reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext);
+ while (next) {
+ switch (next->sType) {
+ case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
+ present_regions = next;
+ break;
+ default:
+ ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x",
+ next->sType);
+ break;
+ }
+ next = reinterpret_cast<const VkPresentRegionsKHR*>(next->pNext);
+ }
+ ALOGV_IF(
+ present_regions &&
+ present_regions->swapchainCount != present_info->swapchainCount,
+ "VkPresentRegions::swapchainCount != VkPresentInfo::swapchainCount");
+ const VkPresentRegionKHR* regions =
+ (present_regions) ? present_regions->pRegions : NULL;
+ const VkAllocationCallbacks* allocator = &GetData(device).allocator;
+ android_native_rect_t* rects = NULL;
+ uint32_t nrects = 0;
+
for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
Swapchain& swapchain =
*SwapchainFromHandle(present_info->pSwapchains[sc]);
uint32_t image_idx = present_info->pImageIndices[sc];
Swapchain::Image& img = swapchain.images[image_idx];
+ const VkPresentRegionKHR* region = (regions) ? ®ions[sc] : NULL;
VkResult swapchain_result = VK_SUCCESS;
VkResult result;
int err;
@@ -888,6 +914,45 @@
present_info->pSwapchains[sc]) {
ANativeWindow* window = swapchain.surface.window.get();
if (swapchain_result == VK_SUCCESS) {
+ if (region) {
+ // Process the incremental-present hint for this swapchain:
+ uint32_t rcount = region->rectangleCount;
+ if (rcount > nrects) {
+ android_native_rect_t* new_rects =
+ static_cast<android_native_rect_t*>(
+ allocator->pfnReallocation(
+ allocator->pUserData, rects,
+ sizeof(android_native_rect_t) * rcount,
+ alignof(android_native_rect_t),
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+ if (new_rects) {
+ rects = new_rects;
+ nrects = rcount;
+ } else {
+ rcount = 0; // Ignore the hint for this swapchain
+ }
+ }
+ for (uint32_t r = 0; r < rcount; ++r) {
+ if (region->pRectangles[r].layer > 0) {
+ ALOGV(
+ "vkQueuePresentKHR ignoring invalid layer "
+ "(%u); using layer 0 instead",
+ region->pRectangles[r].layer);
+ }
+ int x = region->pRectangles[r].offset.x;
+ int y = region->pRectangles[r].offset.y;
+ int width = static_cast<int>(
+ region->pRectangles[r].extent.width);
+ int height = static_cast<int>(
+ region->pRectangles[r].extent.height);
+ android_native_rect_t* cur_rect = &rects[r];
+ cur_rect->left = x;
+ cur_rect->top = y + height;
+ cur_rect->right = x + width;
+ cur_rect->bottom = y;
+ }
+ native_window_set_surface_damage(window, rects, rcount);
+ }
err = window->queueBuffer(window, img.buffer.get(), fence);
// queueBuffer always closes fence, even on error
if (err != 0) {
@@ -918,6 +983,9 @@
if (swapchain_result != final_result)
final_result = WorstPresentResult(final_result, swapchain_result);
}
+ if (rects) {
+ allocator->pfnFree(allocator->pUserData, rects);
+ }
return final_result;
}