Stubbed implementation of VK_GOOGLE_display_timing extension.
This provides the header changes and most of the "boilerplate" changes to add
the VK_GOOGLE_display_timing extension to Vulkan. Future changes will modify
and integrate with the Surface, FrameEvents, and SurfaceFlinger code.
Test: Manually tested that existing apps won't tickle the new-extension paths.
Change-Id: Iec46b1cab4b2561702ebac9a4ae7587584793192
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3e87abf..807b81a 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -122,10 +122,13 @@
struct Swapchain {
Swapchain(Surface& surface_, uint32_t num_images_)
- : surface(surface_), num_images(num_images_) {}
+ : surface(surface_),
+ num_images(num_images_),
+ frame_timestamps_enabled(false) {}
Surface& surface;
uint32_t num_images;
+ bool frame_timestamps_enabled;
struct Image {
Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
@@ -728,6 +731,9 @@
bool active = swapchain->surface.swapchain_handle == swapchain_handle;
ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
+ if (swapchain->frame_timestamps_enabled) {
+ native_window_enable_frame_timestamps(window, false);
+ }
for (uint32_t i = 0; i < swapchain->num_images; i++)
ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
if (active)
@@ -868,7 +874,8 @@
VkResult final_result = VK_SUCCESS;
// Look at the pNext chain for supported extension structs:
- const VkPresentRegionsKHR* present_regions = NULL;
+ const VkPresentRegionsKHR* present_regions = nullptr;
+ const VkPresentTimesInfoGOOGLE* present_times = nullptr;
const VkPresentRegionsKHR* next =
reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext);
while (next) {
@@ -876,6 +883,10 @@
case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
present_regions = next;
break;
+ case VK_STRUCTURE_TYPE_PRESENT_TIMES_GOOGLE:
+ present_times =
+ reinterpret_cast<const VkPresentTimesInfoGOOGLE*>(next);
+ break;
default:
ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x",
next->sType);
@@ -887,10 +898,16 @@
present_regions &&
present_regions->swapchainCount != present_info->swapchainCount,
"VkPresentRegions::swapchainCount != VkPresentInfo::swapchainCount");
+ ALOGV_IF(present_times &&
+ present_times->swapchainCount != present_info->swapchainCount,
+ "VkPresentTimesInfoGOOGLE::swapchainCount != "
+ "VkPresentInfo::swapchainCount");
const VkPresentRegionKHR* regions =
- (present_regions) ? present_regions->pRegions : NULL;
+ (present_regions) ? present_regions->pRegions : nullptr;
+ const VkPresentTimeGOOGLE* times =
+ (present_times) ? present_times->pTimes : nullptr;
const VkAllocationCallbacks* allocator = &GetData(device).allocator;
- android_native_rect_t* rects = NULL;
+ android_native_rect_t* rects = nullptr;
uint32_t nrects = 0;
for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
@@ -898,7 +915,8 @@
*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;
+ const VkPresentRegionKHR* region = (regions) ? ®ions[sc] : nullptr;
+ const VkPresentTimeGOOGLE* time = (times) ? ×[sc] : nullptr;
VkResult swapchain_result = VK_SUCCESS;
VkResult result;
int err;
@@ -955,6 +973,19 @@
}
native_window_set_surface_damage(window, rects, rcount);
}
+ if (time) {
+ if (!swapchain.frame_timestamps_enabled) {
+ native_window_enable_frame_timestamps(window, true);
+ swapchain.frame_timestamps_enabled = true;
+ }
+ // TODO(ianelliott): need to store the presentID (and
+ // desiredPresentTime), so it can be later correlated to
+ // this present. Probably modify the following function
+ // (and below) to plumb a path to store it in FrameEvents
+ // code, on the producer side.
+ native_window_set_buffers_timestamp(
+ window, static_cast<int64_t>(time->desiredPresentTime));
+ }
err = window->queueBuffer(window, img.buffer.get(), fence);
// queueBuffer always closes fence, even on error
if (err != 0) {
@@ -992,5 +1023,44 @@
return final_result;
}
+VKAPI_ATTR
+VkResult GetRefreshCycleDurationGOOGLE(
+ VkDevice,
+ VkSwapchainKHR,
+ VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+ VkResult result = VK_SUCCESS;
+
+ // TODO(ianelliott): FULLY IMPLEMENT THIS FUNCTION!!!
+ pDisplayTimingProperties->minRefreshDuration = 16666666666;
+ pDisplayTimingProperties->maxRefreshDuration = 16666666666;
+
+ return result;
+}
+
+VKAPI_ATTR
+VkResult GetPastPresentationTimingGOOGLE(
+ VkDevice,
+ VkSwapchainKHR swapchain_handle,
+ uint32_t* count,
+ VkPastPresentationTimingGOOGLE* timings) {
+ Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
+ ANativeWindow* window = swapchain.surface.window.get();
+ VkResult result = VK_SUCCESS;
+
+ if (!swapchain.frame_timestamps_enabled) {
+ native_window_enable_frame_timestamps(window, true);
+ swapchain.frame_timestamps_enabled = true;
+ }
+
+ // TODO(ianelliott): FULLY IMPLEMENT THIS FUNCTION!!!
+ if (timings) {
+ *count = 0;
+ } else {
+ *count = 0;
+ }
+
+ return result;
+}
+
} // namespace driver
} // namespace vulkan