swapchain.cpp revision 0e74f00af03b7e705774d0dcf69c2ba8ce7a15a8
1b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall/*
2b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * Copyright 2015 The Android Open Source Project
3b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall *
4b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * Licensed under the Apache License, Version 2.0 (the "License");
5b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * you may not use this file except in compliance with the License.
6b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * You may obtain a copy of the License at
7b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall *
8b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall *      http://www.apache.org/licenses/LICENSE-2.0
9b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall *
10b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * Unless required by applicable law or agreed to in writing, software
11b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * distributed under the License is distributed on an "AS IS" BASIS,
12b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * See the License for the specific language governing permissions and
14b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * limitations under the License.
15b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall */
16b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
17d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// #define LOG_NDEBUG 0
18d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
19d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <algorithm>
20d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <memory>
21d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
22d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <gui/BufferQueue.h>
23b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall#include <log/log.h>
24d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <sync/sync.h>
25d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
26d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include "loader.h"
27d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
28d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallusing namespace vulkan;
29d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
305ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// TODO(jessehall): Currently we don't have a good error code for when a native
315ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// window operation fails. Just returning INITIALIZATION_FAILED for now. Later
325ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// versions (post SDK 0.9) of the API/extension have a better error code.
335ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// When updating to that version, audit all error returns.
345ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall
35d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallnamespace {
36d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
37d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// ----------------------------------------------------------------------------
38d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// These functions/classes form an adaptor that allows objects to be refcounted
39d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// by both android::sp<> and std::shared_ptr<> simultaneously, and delegates
403fbc856120217247c72fb5ed88500000f3881c45Jesse Hall// allocation of the shared_ptr<> control structure to VkAllocationCallbacks.
413fbc856120217247c72fb5ed88500000f3881c45Jesse Hall// The
42d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// platform holds a reference to the ANativeWindow using its embedded reference
43d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// count, and the ANativeWindow implementation holds references to the
44d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// ANativeWindowBuffers using their embedded reference counts, so the
45d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// shared_ptr *must* cooperate with these and hold at least one reference to
46d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// the object using the embedded reference count.
47d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
48d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Halltemplate <typename T>
49d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallstruct NativeBaseDeleter {
50d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    void operator()(T* obj) { obj->common.decRef(&obj->common); }
51d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall};
52d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
5303b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Halltemplate <typename Host>
5403b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hallstruct AllocScope {};
5503b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall
5603b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Halltemplate <>
5703b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hallstruct AllocScope<VkInstance> {
583fbc856120217247c72fb5ed88500000f3881c45Jesse Hall    static const VkSystemAllocationScope kScope =
593fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE;
6003b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall};
6103b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall
6203b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Halltemplate <>
6303b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hallstruct AllocScope<VkDevice> {
643fbc856120217247c72fb5ed88500000f3881c45Jesse Hall    static const VkSystemAllocationScope kScope =
653fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE;
6603b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall};
6703b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall
681356b0d3179254a7a27e88abb2d2500385469f14Jesse Halltemplate <typename T, typename Host>
69d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallclass VulkanAllocator {
70d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall   public:
71d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    typedef T value_type;
72d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
731356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    explicit VulkanAllocator(Host host) : host_(host) {}
74d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
75d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    template <typename U>
761356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    explicit VulkanAllocator(const VulkanAllocator<U, Host>& other)
771356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        : host_(other.host_) {}
78d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
79d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    T* allocate(size_t n) const {
801356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        return static_cast<T*>(AllocMem(host_, n * sizeof(T), alignof(T),
8103b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall                                        AllocScope<Host>::kScope));
82d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
831356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    void deallocate(T* p, size_t) const { return FreeMem(host_, p); }
84d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
85d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall   private:
861356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    template <typename U, typename H>
87d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    friend class VulkanAllocator;
881356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Host host_;
89d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall};
90d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
911356b0d3179254a7a27e88abb2d2500385469f14Jesse Halltemplate <typename T, typename Host>
921356b0d3179254a7a27e88abb2d2500385469f14Jesse Hallstd::shared_ptr<T> InitSharedPtr(Host host, T* obj) {
93d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    obj->common.incRef(&obj->common);
94d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return std::shared_ptr<T>(obj, NativeBaseDeleter<T>(),
951356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall                              VulkanAllocator<T, Host>(host));
96d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
97d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
98d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// ----------------------------------------------------------------------------
99d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1001356b0d3179254a7a27e88abb2d2500385469f14Jesse Hallstruct Surface {
1011356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    std::shared_ptr<ANativeWindow> window;
1021356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall};
1031356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
1041356b0d3179254a7a27e88abb2d2500385469f14Jesse HallVkSurfaceKHR HandleFromSurface(Surface* surface) {
1051356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface));
1061356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
1071356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
1081356b0d3179254a7a27e88abb2d2500385469f14Jesse HallSurface* SurfaceFromHandle(VkSurfaceKHR handle) {
109a3a7a1d37bdfad56245b75edac49f8aceded321dJesse Hall    return reinterpret_cast<Surface*>(handle);
1101356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
1111356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
112d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallstruct Swapchain {
1131356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Swapchain(Surface& surface_, uint32_t num_images_)
1141356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        : surface(surface_), num_images(num_images_) {}
115d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1161356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface& surface;
117d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t num_images;
118d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
119d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    struct Image {
120d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
121d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VkImage image;
122d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        std::shared_ptr<ANativeWindowBuffer> buffer;
123d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // The fence is only valid when the buffer is dequeued, and should be
124d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // -1 any other time. When valid, we own the fd, and must ensure it is
125d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // closed: either by closing it explicitly when queueing the buffer,
126d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
127d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        int dequeue_fence;
128d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        bool dequeued;
129d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    } images[android::BufferQueue::NUM_BUFFER_SLOTS];
130d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall};
131d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
132d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallVkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
133d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain));
134d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
135d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
136d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallSwapchain* SwapchainFromHandle(VkSwapchainKHR handle) {
137a3a7a1d37bdfad56245b75edac49f8aceded321dJesse Hall    return reinterpret_cast<Swapchain*>(handle);
138d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
139d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
140d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}  // anonymous namespace
141b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
142b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hallnamespace vulkan {
143b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
144e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
1451356b0d3179254a7a27e88abb2d2500385469f14Jesse HallVkResult CreateAndroidSurfaceKHR(VkInstance instance,
1461356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall                                 ANativeWindow* window,
1470e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall                                 const VkAllocationCallbacks* /*allocator*/,
1481356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall                                 VkSurfaceKHR* out_surface) {
1491356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    void* mem = AllocMem(instance, sizeof(Surface), alignof(Surface),
1503fbc856120217247c72fb5ed88500000f3881c45Jesse Hall                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1511356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (!mem)
1521356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        return VK_ERROR_OUT_OF_HOST_MEMORY;
1531356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface* surface = new (mem) Surface;
154b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
1551356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    surface->window = InitSharedPtr(instance, window);
156b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
1571356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
1581356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    int err =
1591356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
1601356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (err != 0) {
1611356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
1621356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        // errors and translate them to valid Vulkan result codes?
1631356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
1641356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall              err);
1651356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        surface->~Surface();
1661356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        FreeMem(instance, surface);
1671356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
1681356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    }
169b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
1701356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    *out_surface = HandleFromSurface(surface);
171b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
172b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
173b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
174e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
1750e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hallvoid DestroySurfaceKHR(VkInstance instance,
1760e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall                       VkSurfaceKHR surface_handle,
1770e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall                       const VkAllocationCallbacks* /*allocator*/) {
1781356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface* surface = SurfaceFromHandle(surface_handle);
1791356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (!surface)
1801356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        return;
1811356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL);
1821356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    surface->~Surface();
1831356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    FreeMem(instance, surface);
1841356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
1851356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
186e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
187a64292517b1876c4bbe5d3e62c577812f40bd922Jesse HallVkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
1881356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall                                            uint32_t /*queue_family*/,
189b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall                                            VkSurfaceKHR /*surface*/,
1900e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall                                            VkBool32* supported) {
1910e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall    *supported = VK_TRUE;
192a64292517b1876c4bbe5d3e62c577812f40bd922Jesse Hall    return VK_SUCCESS;
1931356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
1941356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
195e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
196b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse HallVkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
197b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    VkPhysicalDevice /*pdev*/,
198b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    VkSurfaceKHR surface,
199b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    VkSurfaceCapabilitiesKHR* capabilities) {
200d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int err;
2011356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
202d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
203d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int width, height;
204d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
205d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
206d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
207d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              strerror(-err), err);
2085ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
209d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
210d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
211d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
212d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
213d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              strerror(-err), err);
2145ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
215d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
216d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
217b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->currentExtent = VkExtent2D{width, height};
218d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
219d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): Figure out what the min/max values should be.
220b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->minImageCount = 2;
221b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->maxImageCount = 3;
222d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
223d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): Figure out what the max extent should be. Maximum
224d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // texture dimension maybe?
225b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->minImageExtent = VkExtent2D{1, 1};
226b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->maxImageExtent = VkExtent2D{4096, 4096};
227d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
228d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): We can support all transforms, fix this once
229d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // implemented.
230b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_KHR;
231d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
232d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): Implement based on NATIVE_WINDOW_TRANSFORM_HINT.
233b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->currentTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
234d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
235b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->maxImageArraySize = 1;
236d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
237d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): I think these are right, but haven't thought hard about
238d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // it. Do we need to query the driver for support of any of these?
239d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // Currently not included:
240d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // - VK_IMAGE_USAGE_GENERAL: maybe? does this imply cpu mappable?
241d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not
242d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not
243b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->supportedUsageFlags =
2443fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
2453fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
2463fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
247d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
248d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
249b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
250b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
251b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
252e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
253b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse HallVkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice /*pdev*/,
254b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall                                            VkSurfaceKHR /*surface*/,
255b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall                                            uint32_t* count,
256b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall                                            VkSurfaceFormatKHR* formats) {
2571356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // TODO(jessehall): Fill out the set of supported formats. Longer term, add
2581356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // a new gralloc method to query whether a (format, usage) pair is
2591356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // supported, and check that for each gralloc format that corresponds to a
2601356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // Vulkan format. Shorter term, just add a few more formats to the ones
2611356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // hardcoded below.
262d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
263d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const VkSurfaceFormatKHR kFormats[] = {
264d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        {VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR},
265d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        {VK_FORMAT_R8G8B8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR},
266d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
267d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
268d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
269d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
270d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (formats) {
271d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (*count < kNumFormats)
272d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            result = VK_INCOMPLETE;
273d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        std::copy(kFormats, kFormats + std::min(*count, kNumFormats), formats);
274d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
275d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *count = kNumFormats;
276d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return result;
277b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
278b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
279e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
280b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse HallVkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice /*pdev*/,
281b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall                                                 VkSurfaceKHR /*surface*/,
282b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall                                                 uint32_t* count,
283b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall                                                 VkPresentModeKHR* modes) {
284d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const VkPresentModeKHR kModes[] = {
285d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR,
286d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
287d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const uint32_t kNumModes = sizeof(kModes) / sizeof(kModes[0]);
288d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
289d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
290d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (modes) {
291d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (*count < kNumModes)
292d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            result = VK_INCOMPLETE;
293d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        std::copy(kModes, kModes + std::min(*count, kNumModes), modes);
294d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
295d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *count = kNumModes;
296d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return result;
297b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
298b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
299e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
300b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse HallVkResult CreateSwapchainKHR(VkDevice device,
301b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall                            const VkSwapchainCreateInfoKHR* create_info,
3020e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall                            const VkAllocationCallbacks* /*allocator*/,
303d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                            VkSwapchainKHR* swapchain_handle) {
304d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int err;
305d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
306d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
307d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGV_IF(create_info->imageArraySize != 1,
308d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             "Swapchain imageArraySize (%u) != 1 not supported",
309d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             create_info->imageArraySize);
310d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
311d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGE_IF(create_info->imageFormat != VK_FORMAT_R8G8B8A8_UNORM,
312d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             "swapchain formats other than R8G8B8A8_UNORM not yet implemented");
313d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGE_IF(create_info->imageColorSpace != VK_COLORSPACE_SRGB_NONLINEAR_KHR,
314d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             "color spaces other than SRGB_NONLINEAR not yet implemented");
315d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGE_IF(create_info->oldSwapchain,
316d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             "swapchain re-creation not yet implemented");
317d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGE_IF(create_info->preTransform != VK_SURFACE_TRANSFORM_NONE_KHR,
318d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             "swapchain preTransform not yet implemented");
319d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGE_IF(create_info->presentMode != VK_PRESENT_MODE_FIFO_KHR,
320d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             "present modes other than FIFO are not yet implemented");
321d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
322d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Configure the native window --
323d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
3241356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface& surface = *SurfaceFromHandle(create_info->surface);
32570f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    const DeviceVtbl& driver_vtbl = GetDriverVtbl(device);
32670f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall
3271356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    err = native_window_set_buffers_dimensions(surface.window.get(),
328d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                                               create_info->imageExtent.width,
329d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                                               create_info->imageExtent.height);
330d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
331d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
332d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
333d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
334d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              create_info->imageExtent.width, create_info->imageExtent.height,
335d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              strerror(-err), err);
3365ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
337d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
338d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
339f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall    err = native_window_set_scaling_mode(
3401356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
341f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall    if (err != 0) {
342f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
343f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        // errors and translate them to valid Vulkan result codes?
344f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
345f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall              strerror(-err), err);
346f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
347f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall    }
348f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall
349d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t min_undequeued_buffers;
3501356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    err = surface.window->query(
3511356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        surface.window.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
3521356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        reinterpret_cast<int*>(&min_undequeued_buffers));
353d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
354d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
355d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
356d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("window->query failed: %s (%d)", strerror(-err), err);
3575ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
358d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
359d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t num_images =
360d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        (create_info->minImageCount - 1) + min_undequeued_buffers;
3611356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    err = native_window_set_buffer_count(surface.window.get(), num_images);
362d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
363d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
364d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
365d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
366d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              err);
3675ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
368d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
369d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
37070f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    int gralloc_usage = 0;
37170f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    // TODO(jessehall): Remove conditional once all drivers have been updated
37270f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    if (driver_vtbl.GetSwapchainGrallocUsageANDROID) {
37370f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        result = driver_vtbl.GetSwapchainGrallocUsageANDROID(
37470f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall            device, create_info->imageFormat, create_info->imageUsageFlags,
37570f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall            &gralloc_usage);
37670f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        if (result != VK_SUCCESS) {
37770f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall            ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
37870f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall            return VK_ERROR_INITIALIZATION_FAILED;
37970f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        }
38070f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    } else {
38170f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        gralloc_usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
38270f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    }
3831356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    err = native_window_set_usage(surface.window.get(), gralloc_usage);
38470f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    if (err != 0) {
38570f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
38670f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        // errors and translate them to valid Vulkan result codes?
38770f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
38870f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
38970f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    }
390d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
391d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Allocate our Swapchain object --
392d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // After this point, we must deallocate the swapchain on error.
393d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
3941356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    void* mem = AllocMem(device, sizeof(Swapchain), alignof(Swapchain),
3953fbc856120217247c72fb5ed88500000f3881c45Jesse Hall                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
3961356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (!mem)
397d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return VK_ERROR_OUT_OF_HOST_MEMORY;
3981356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Swapchain* swapchain = new (mem) Swapchain(surface, num_images);
399d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
400d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Dequeue all buffers and create a VkImage for each --
401d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // Any failures during or after this must cancel the dequeued buffers.
402d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
403d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkNativeBufferANDROID image_native_buffer = {
404d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// TODO(jessehall): Figure out how to make extension headers not horrible.
405d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic push
406d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wold-style-cast"
407d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
408d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic pop
409d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .pNext = nullptr,
410d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
411d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkImageCreateInfo image_create = {
412d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
413d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .pNext = &image_native_buffer,
414d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .imageType = VK_IMAGE_TYPE_2D,
415d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .format = VK_FORMAT_R8G8B8A8_UNORM,  // TODO(jessehall)
416d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .extent = {0, 0, 1},
417d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .mipLevels = 1,
418a15a4bf4bafd6114ae8f28c2df2fc622cb3baaceJesse Hall        .arrayLayers = 1,
419091ed9e69400edcc549c9b11635d1a305d6b5a83Jesse Hall        .samples = VK_SAMPLE_COUNT_1_BIT,
420d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .tiling = VK_IMAGE_TILING_OPTIMAL,
421d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .usage = create_info->imageUsageFlags,
422d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .flags = 0,
423d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .sharingMode = create_info->sharingMode,
42403b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall        .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
425d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
426d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
427d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
428d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (uint32_t i = 0; i < num_images; i++) {
429d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Swapchain::Image& img = swapchain->images[i];
430d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
431d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ANativeWindowBuffer* buffer;
4321356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        err = surface.window->dequeueBuffer(surface.window.get(), &buffer,
4331356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall                                            &img.dequeue_fence);
434d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (err != 0) {
435d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // TODO(jessehall): Improve error reporting. Can we enumerate
436d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // possible errors and translate them to valid Vulkan result codes?
437d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
4385ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall            result = VK_ERROR_INITIALIZATION_FAILED;
439d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            break;
440d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
441d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        img.buffer = InitSharedPtr(device, buffer);
442d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        img.dequeued = true;
443d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
444d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_create.extent =
445d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            VkExtent3D{img.buffer->width, img.buffer->height, 1};
446d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.handle = img.buffer->handle;
447d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.stride = img.buffer->stride;
448d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.format = img.buffer->format;
449d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.usage = img.buffer->usage;
450d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
45103b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall        result =
45203b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall            driver_vtbl.CreateImage(device, &image_create, nullptr, &img.image);
453d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (result != VK_SUCCESS) {
454d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGD("vkCreateImage w/ native buffer failed: %u", result);
455d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            break;
456d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
457d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
458d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
459d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Cancel all buffers, returning them to the queue --
460d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // If an error occurred before, also destroy the VkImage and release the
461d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // buffer reference. Otherwise, we retain a strong reference to the buffer.
462d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    //
463d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): The error path here is the same as DestroySwapchain,
464d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // but not the non-error path. Should refactor/unify.
465d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (uint32_t i = 0; i < num_images; i++) {
466d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Swapchain::Image& img = swapchain->images[i];
467d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (img.dequeued) {
4681356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall            surface.window->cancelBuffer(surface.window.get(), img.buffer.get(),
4691356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall                                         img.dequeue_fence);
470d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            img.dequeue_fence = -1;
471d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            img.dequeued = false;
472d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
473d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (result != VK_SUCCESS) {
474d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            if (img.image)
47503b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall                driver_vtbl.DestroyImage(device, img.image, nullptr);
476d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
477d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
478d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
479d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (result != VK_SUCCESS) {
480d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        swapchain->~Swapchain();
4811356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        FreeMem(device, swapchain);
482d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return result;
483d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
484d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
485d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *swapchain_handle = HandleFromSwapchain(swapchain);
486b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
487b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
488b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
489e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
4900e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse HallVkResult DestroySwapchainKHR(VkDevice device,
4910e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall                             VkSwapchainKHR swapchain_handle,
4920e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall                             const VkAllocationCallbacks* /*allocator*/) {
493d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const DeviceVtbl& driver_vtbl = GetDriverVtbl(device);
494d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
4951356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    const std::shared_ptr<ANativeWindow>& window = swapchain->surface.window;
496d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
497d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (uint32_t i = 0; i < swapchain->num_images; i++) {
498d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Swapchain::Image& img = swapchain->images[i];
499d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (img.dequeued) {
500d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            window->cancelBuffer(window.get(), img.buffer.get(),
501d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                                 img.dequeue_fence);
502d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            img.dequeue_fence = -1;
503d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            img.dequeued = false;
504d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
505d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (img.image) {
50603b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall            driver_vtbl.DestroyImage(device, img.image, nullptr);
507d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
508d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
509d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
510d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    swapchain->~Swapchain();
5111356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    FreeMem(device, swapchain);
512d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
513b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
514b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
515b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
516e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
517d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallVkResult GetSwapchainImagesKHR(VkDevice,
518d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                               VkSwapchainKHR swapchain_handle,
519b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall                               uint32_t* count,
520d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                               VkImage* images) {
521d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
522d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
523d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (images) {
524d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        uint32_t n = swapchain.num_images;
525d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (*count < swapchain.num_images) {
526d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            n = *count;
527d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            result = VK_INCOMPLETE;
528d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
529d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        for (uint32_t i = 0; i < n; i++)
530d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            images[i] = swapchain.images[i].image;
531d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
532d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *count = swapchain.num_images;
533d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return result;
534b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
535b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
536e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
537b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse HallVkResult AcquireNextImageKHR(VkDevice device,
538d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                             VkSwapchainKHR swapchain_handle,
539b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall                             uint64_t timeout,
540b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall                             VkSemaphore semaphore,
541b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall                             uint32_t* image_index) {
542d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
5431356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    ANativeWindow* window = swapchain.surface.window.get();
544d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result;
545d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int err;
546d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
547d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGW_IF(
548d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        timeout != UINT64_MAX,
549d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented");
550d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
551d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ANativeWindowBuffer* buffer;
552d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int fence;
5531356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    err = window->dequeueBuffer(window, &buffer, &fence);
554d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
555d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
556d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
557d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
5585ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
559d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
560d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
561d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t idx;
562d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (idx = 0; idx < swapchain.num_images; idx++) {
563d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (swapchain.images[idx].buffer.get() == buffer) {
564d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            swapchain.images[idx].dequeued = true;
565d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            swapchain.images[idx].dequeue_fence = fence;
566d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            break;
567d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
568d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
569d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (idx == swapchain.num_images) {
570d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("dequeueBuffer returned unrecognized buffer");
5711356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        window->cancelBuffer(window, buffer, fence);
572d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic push
573d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wold-style-cast"
574d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return VK_ERROR_OUT_OF_DATE_KHR;
575d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic pop
576d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
577d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
578d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int fence_clone = -1;
579d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (fence != -1) {
580d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        fence_clone = dup(fence);
581d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (fence_clone == -1) {
582d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGE("dup(fence) failed, stalling until signalled: %s (%d)",
583d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                  strerror(errno), errno);
584d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            sync_wait(fence, -1 /* forever */);
585d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
586d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
587d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
588d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const DeviceVtbl& driver_vtbl = GetDriverVtbl(device);
589ab9aeef063119445b59166f781c464c64e3909dbJesse Hall    if (driver_vtbl.AcquireImageANDROID) {
590ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        result = driver_vtbl.AcquireImageANDROID(
591ab9aeef063119445b59166f781c464c64e3909dbJesse Hall            device, swapchain.images[idx].image, fence_clone, semaphore);
592ab9aeef063119445b59166f781c464c64e3909dbJesse Hall    } else {
593ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        ALOG_ASSERT(driver_vtbl.ImportNativeFenceANDROID,
594ab9aeef063119445b59166f781c464c64e3909dbJesse Hall                    "Have neither vkAcquireImageANDROID nor "
595ab9aeef063119445b59166f781c464c64e3909dbJesse Hall                    "vkImportNativeFenceANDROID");
596ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        result = driver_vtbl.ImportNativeFenceANDROID(device, semaphore,
597ab9aeef063119445b59166f781c464c64e3909dbJesse Hall                                                      fence_clone);
598ab9aeef063119445b59166f781c464c64e3909dbJesse Hall    }
599d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (result != VK_SUCCESS) {
600ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // NOTE: we're relying on AcquireImageANDROID to close fence_clone,
601ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // even if the call fails. We could close it ourselves on failure, but
602ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // that would create a race condition if the driver closes it on a
603ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // failure path: some other thread might create an fd with the same
604ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // number between the time the driver closes it and the time we close
605ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // it. We must assume one of: the driver *always* closes it even on
606ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // failure, or *never* closes it on failure.
6071356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        window->cancelBuffer(window, buffer, fence);
608d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        swapchain.images[idx].dequeued = false;
609d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        swapchain.images[idx].dequeue_fence = -1;
610d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return result;
611d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
612d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
613d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *image_index = idx;
614b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
615b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
616b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
617e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
618b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse HallVkResult QueuePresentKHR(VkQueue queue, VkPresentInfoKHR* present_info) {
619d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic push
620d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wold-style-cast"
621d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wsign-conversion"
622d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
623d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
624d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             present_info->sType);
625b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall#pragma clang diagnostic pop
626d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGV_IF(present_info->pNext, "VkPresentInfo::pNext != NULL");
627d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
628d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const DeviceVtbl& driver_vtbl = GetDriverVtbl(queue);
629d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult final_result = VK_SUCCESS;
630d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
631d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Swapchain& swapchain =
63203b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall            *SwapchainFromHandle(present_info->pSwapchains[sc]);
6331356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        ANativeWindow* window = swapchain.surface.window.get();
634d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        uint32_t image_idx = present_info->imageIndices[sc];
6355ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        Swapchain::Image& img = swapchain.images[image_idx];
636d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VkResult result;
637d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        int err;
638d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
639d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        int fence = -1;
640ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        if (driver_vtbl.QueueSignalReleaseImageANDROID) {
641ab9aeef063119445b59166f781c464c64e3909dbJesse Hall            result = driver_vtbl.QueueSignalReleaseImageANDROID(
642ab9aeef063119445b59166f781c464c64e3909dbJesse Hall                queue, img.image, &fence);
643ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        } else {
644ab9aeef063119445b59166f781c464c64e3909dbJesse Hall            ALOG_ASSERT(driver_vtbl.QueueSignalNativeFenceANDROID,
645ab9aeef063119445b59166f781c464c64e3909dbJesse Hall                        "Have neither vkQueueSignalReleaseImageANDROID nor "
646ab9aeef063119445b59166f781c464c64e3909dbJesse Hall                        "vkQueueSignalNativeFenceANDROID");
647ab9aeef063119445b59166f781c464c64e3909dbJesse Hall            result = driver_vtbl.QueueSignalNativeFenceANDROID(queue, &fence);
648ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        }
649d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (result != VK_SUCCESS) {
650ab9aeef063119445b59166f781c464c64e3909dbJesse Hall            ALOGE("QueueSignalReleaseImageANDROID failed: %d", result);
651a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall            if (present_info->pResults)
652a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall                present_info->pResults[sc] = result;
653d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            if (final_result == VK_SUCCESS)
654d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                final_result = result;
655d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // TODO(jessehall): What happens to the buffer here? Does the app
656d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // still own it or not, i.e. should we cancel the buffer? Hard to
657d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // do correctly without synchronizing, though I guess we could wait
658d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // for the queue to idle.
659d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            continue;
660d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
661d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
6621356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        err = window->queueBuffer(window, img.buffer.get(), fence);
663d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (err != 0) {
664d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // TODO(jessehall): What now? We should probably cancel the buffer,
665d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // I guess?
666d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
667a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall            if (present_info->pResults)
668a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall                present_info->pResults[sc] = result;
669d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            if (final_result == VK_SUCCESS)
6705ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall                final_result = VK_ERROR_INITIALIZATION_FAILED;
671d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            continue;
672d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
673d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
674d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (img.dequeue_fence != -1) {
675d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            close(img.dequeue_fence);
676d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            img.dequeue_fence = -1;
677d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
678d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        img.dequeued = false;
679a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall
680a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall        if (present_info->pResults)
681a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall            present_info->pResults[sc] = VK_SUCCESS;
682d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
683d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
684d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return final_result;
685d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
686b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
687b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}  // namespace vulkan
688