[go: nahoru, domu]

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#include <algorithm>
18d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
19d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <gui/BufferQueue.h>
20b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall#include <log/log.h>
21d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <sync/sync.h>
22e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu#include <utils/StrongPointer.h>
23d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
244a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu#include "driver.h"
25d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
265ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// TODO(jessehall): Currently we don't have a good error code for when a native
275ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// window operation fails. Just returning INITIALIZATION_FAILED for now. Later
285ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// versions (post SDK 0.9) of the API/extension have a better error code.
295ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// When updating to that version, audit all error returns.
30622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wunamespace vulkan {
31622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wunamespace driver {
325ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall
33d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallnamespace {
34d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
3555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hallconst VkSurfaceTransformFlagsKHR kSupportedTransforms =
3655bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR |
3755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
3855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR |
3955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR |
4055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
4155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
4255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
4355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
4455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
4555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
4655bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
4755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse HallVkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) {
4855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // Native and Vulkan transforms are isomorphic, but are represented
4955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // differently. Vulkan transforms are built up of an optional horizontal
5055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // mirror, followed by a clockwise 0/90/180/270-degree rotation. Native
5155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // transforms are built up from a horizontal flip, vertical flip, and
5255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // 90-degree rotation, all optional but always in that order.
5355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
5455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // TODO(jessehall): For now, only support pure rotations, not
5555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // flip or flip-and-rotate, until I have more time to test them and build
5655bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // sample code. As far as I know we never actually use anything besides
5755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // pure rotations anyway.
5855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
5955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    switch (native) {
6055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case 0:  // 0x0
6155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
6255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        // case NATIVE_WINDOW_TRANSFORM_FLIP_H:  // 0x1
6355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
6455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        // case NATIVE_WINDOW_TRANSFORM_FLIP_V:  // 0x2
6555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
6655bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case NATIVE_WINDOW_TRANSFORM_ROT_180:  // FLIP_H | FLIP_V
6755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
6855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case NATIVE_WINDOW_TRANSFORM_ROT_90:  // 0x4
6955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
7055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        // case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
7155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
7255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        // case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
7355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
7455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case NATIVE_WINDOW_TRANSFORM_ROT_270:  // FLIP_H | FLIP_V | ROT_90
7555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
7655bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
7755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        default:
7855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
7955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    }
8055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall}
8155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
82178b69664a5f56470c143b5930162f285adc83faJesse Hallint InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) {
83178b69664a5f56470c143b5930162f285adc83faJesse Hall    switch (transform) {
84178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
85178b69664a5f56470c143b5930162f285adc83faJesse Hall            return NATIVE_WINDOW_TRANSFORM_ROT_270;
86178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
87178b69664a5f56470c143b5930162f285adc83faJesse Hall            return NATIVE_WINDOW_TRANSFORM_ROT_180;
88178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
89178b69664a5f56470c143b5930162f285adc83faJesse Hall            return NATIVE_WINDOW_TRANSFORM_ROT_90;
90178b69664a5f56470c143b5930162f285adc83faJesse Hall        // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
91178b69664a5f56470c143b5930162f285adc83faJesse Hall        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
92178b69664a5f56470c143b5930162f285adc83faJesse Hall        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H;
93178b69664a5f56470c143b5930162f285adc83faJesse Hall        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
94178b69664a5f56470c143b5930162f285adc83faJesse Hall        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H |
95178b69664a5f56470c143b5930162f285adc83faJesse Hall        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
96178b69664a5f56470c143b5930162f285adc83faJesse Hall        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
97178b69664a5f56470c143b5930162f285adc83faJesse Hall        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V;
98178b69664a5f56470c143b5930162f285adc83faJesse Hall        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
99178b69664a5f56470c143b5930162f285adc83faJesse Hall        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V |
100178b69664a5f56470c143b5930162f285adc83faJesse Hall        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
101178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
102178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
103178b69664a5f56470c143b5930162f285adc83faJesse Hall        default:
104178b69664a5f56470c143b5930162f285adc83faJesse Hall            return 0;
105178b69664a5f56470c143b5930162f285adc83faJesse Hall    }
106178b69664a5f56470c143b5930162f285adc83faJesse Hall}
107178b69664a5f56470c143b5930162f285adc83faJesse Hall
108d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// ----------------------------------------------------------------------------
109d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1101356b0d3179254a7a27e88abb2d2500385469f14Jesse Hallstruct Surface {
111e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu    android::sp<ANativeWindow> window;
112dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    VkSwapchainKHR swapchain_handle;
1131356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall};
1141356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
1151356b0d3179254a7a27e88abb2d2500385469f14Jesse HallVkSurfaceKHR HandleFromSurface(Surface* surface) {
1161356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface));
1171356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
1181356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
1191356b0d3179254a7a27e88abb2d2500385469f14Jesse HallSurface* SurfaceFromHandle(VkSurfaceKHR handle) {
120a3a7a1d37bdfad56245b75edac49f8aceded321dJesse Hall    return reinterpret_cast<Surface*>(handle);
1211356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
1221356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
123d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallstruct Swapchain {
1241356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Swapchain(Surface& surface_, uint32_t num_images_)
1251356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        : surface(surface_), num_images(num_images_) {}
126d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1271356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface& surface;
128d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t num_images;
129d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
130d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    struct Image {
131d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
132d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VkImage image;
133e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu        android::sp<ANativeWindowBuffer> buffer;
134d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // The fence is only valid when the buffer is dequeued, and should be
135d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // -1 any other time. When valid, we own the fd, and must ensure it is
136d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // closed: either by closing it explicitly when queueing the buffer,
137d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
138d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        int dequeue_fence;
139d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        bool dequeued;
140d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    } images[android::BufferQueue::NUM_BUFFER_SLOTS];
141d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall};
142d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
143d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallVkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
144d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain));
145d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
146d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
147d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallSwapchain* SwapchainFromHandle(VkSwapchainKHR handle) {
148a3a7a1d37bdfad56245b75edac49f8aceded321dJesse Hall    return reinterpret_cast<Swapchain*>(handle);
149d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
150d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
151dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hallvoid ReleaseSwapchainImage(VkDevice device,
152dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                           ANativeWindow* window,
153dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                           int release_fence,
154dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                           Swapchain::Image& image) {
155dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOG_ASSERT(release_fence == -1 || image.dequeued,
156dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                "ReleaseSwapchainImage: can't provide a release fence for "
157dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                "non-dequeued images");
158dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
159dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (image.dequeued) {
160dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (release_fence >= 0) {
161dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // We get here from vkQueuePresentKHR. The application is
162dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // responsible for creating an execution dependency chain from
163dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // vkAcquireNextImage (dequeue_fence) to vkQueuePresentKHR
164dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // (release_fence), so we can drop the dequeue_fence here.
165dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            if (image.dequeue_fence >= 0)
166dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                close(image.dequeue_fence);
167dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        } else {
168dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // We get here during swapchain destruction, or various serious
169dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // error cases e.g. when we can't create the release_fence during
170dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // vkQueuePresentKHR. In non-error cases, the dequeue_fence should
171dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // have already signalled, since the swapchain images are supposed
172dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // to be idle before the swapchain is destroyed. In error cases,
173dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // there may be rendering in flight to the image, but since we
174dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // weren't able to create a release_fence, waiting for the
175dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // dequeue_fence is about the best we can do.
176dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            release_fence = image.dequeue_fence;
177dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        }
178dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        image.dequeue_fence = -1;
179dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
180dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (window) {
181dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            window->cancelBuffer(window, image.buffer.get(), release_fence);
182dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        } else {
183dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            if (release_fence >= 0) {
184dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                sync_wait(release_fence, -1 /* forever */);
185dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                close(release_fence);
186dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            }
187dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        }
188dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
189dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        image.dequeued = false;
190dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
191dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
192dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (image.image) {
193dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        GetData(device).driver.DestroyImage(device, image.image, nullptr);
194dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        image.image = VK_NULL_HANDLE;
195dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
196dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
197dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    image.buffer.clear();
198dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall}
199dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
200dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hallvoid OrphanSwapchain(VkDevice device, Swapchain* swapchain) {
201dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (swapchain->surface.swapchain_handle != HandleFromSwapchain(swapchain))
202dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        return;
203dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    for (uint32_t i = 0; i < swapchain->num_images; i++) {
204dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (!swapchain->images[i].dequeued)
205dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            ReleaseSwapchainImage(device, nullptr, -1, swapchain->images[i]);
206dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
207dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
208dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall}
209dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
210d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}  // anonymous namespace
211b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
212e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
213622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult CreateAndroidSurfaceKHR(
214f9fa9a50d5e87dacce36ef2a56b392fc053cf8ceJesse Hall    VkInstance instance,
215f9fa9a50d5e87dacce36ef2a56b392fc053cf8ceJesse Hall    const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
216f9fa9a50d5e87dacce36ef2a56b392fc053cf8ceJesse Hall    const VkAllocationCallbacks* allocator,
217f9fa9a50d5e87dacce36ef2a56b392fc053cf8ceJesse Hall    VkSurfaceKHR* out_surface) {
2181f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    if (!allocator)
2194a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu        allocator = &GetData(instance).allocator;
2201f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Surface),
2211f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                                         alignof(Surface),
2221f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2231356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (!mem)
2241356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        return VK_ERROR_OUT_OF_HOST_MEMORY;
2251356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface* surface = new (mem) Surface;
226b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
227e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu    surface->window = pCreateInfo->window;
228dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    surface->swapchain_handle = VK_NULL_HANDLE;
229b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
2301356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
2311356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    int err =
2321356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
2331356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (err != 0) {
2341356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
2351356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        // errors and translate them to valid Vulkan result codes?
2361356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
2371356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall              err);
2381356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        surface->~Surface();
2391f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall        allocator->pfnFree(allocator->pUserData, surface);
2401356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
2411356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    }
242b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
2431356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    *out_surface = HandleFromSurface(surface);
244b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
245b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
246b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
247e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
248622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wuvoid DestroySurfaceKHR(VkInstance instance,
249622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                       VkSurfaceKHR surface_handle,
250622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                       const VkAllocationCallbacks* allocator) {
2511356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface* surface = SurfaceFromHandle(surface_handle);
2521356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (!surface)
2531356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        return;
2541356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL);
25542a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ALOGV_IF(surface->swapchain_handle != VK_NULL_HANDLE,
256dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "destroyed VkSurfaceKHR 0x%" PRIx64
257dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             " has active VkSwapchainKHR 0x%" PRIx64,
258dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             reinterpret_cast<uint64_t>(surface_handle),
259dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             reinterpret_cast<uint64_t>(surface->swapchain_handle));
2601356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    surface->~Surface();
2611f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    if (!allocator)
2624a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu        allocator = &GetData(instance).allocator;
2631f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    allocator->pfnFree(allocator->pUserData, surface);
2641356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
2651356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
266e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
267622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
268622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            uint32_t /*queue_family*/,
269622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            VkSurfaceKHR /*surface*/,
270622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            VkBool32* supported) {
2710e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall    *supported = VK_TRUE;
272a64292517b1876c4bbe5d3e62c577812f40bd922Jesse Hall    return VK_SUCCESS;
2731356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
2741356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
275e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
276622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
277b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    VkPhysicalDevice /*pdev*/,
278b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    VkSurfaceKHR surface,
279b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    VkSurfaceCapabilitiesKHR* capabilities) {
280d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int err;
2811356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
282d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
283d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int width, height;
284d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
285d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
286d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
287d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              strerror(-err), err);
2885ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
289d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
290d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
291d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
292d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
293d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              strerror(-err), err);
2945ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
295d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
296d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
29755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    int transform_hint;
29855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
29955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    if (err != 0) {
30055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
30155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall              strerror(-err), err);
30255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
30355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    }
30455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
305d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): Figure out what the min/max values should be.
306b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->minImageCount = 2;
307b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->maxImageCount = 3;
308d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
309fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    capabilities->currentExtent =
310fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall        VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
311fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall
312d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): Figure out what the max extent should be. Maximum
313d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // texture dimension maybe?
314b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->minImageExtent = VkExtent2D{1, 1};
315b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->maxImageExtent = VkExtent2D{4096, 4096};
316d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
317fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    capabilities->maxImageArrayLayers = 1;
318fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall
31955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    capabilities->supportedTransforms = kSupportedTransforms;
32055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    capabilities->currentTransform =
32155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        TranslateNativeToVulkanTransform(transform_hint);
322d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
323fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    // On Android, window composition is a WindowManager property, not something
324fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    // associated with the bufferqueue. It can't be changed from here.
325fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
326d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
327d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): I think these are right, but haven't thought hard about
328d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // it. Do we need to query the driver for support of any of these?
329d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // Currently not included:
330d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // - VK_IMAGE_USAGE_GENERAL: maybe? does this imply cpu mappable?
331d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not
332d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not
333b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->supportedUsageFlags =
3343fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
3353fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
3363fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
337d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
338d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
339b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
340b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
341b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
342e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
343622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice /*pdev*/,
344622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            VkSurfaceKHR /*surface*/,
345622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            uint32_t* count,
346622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            VkSurfaceFormatKHR* formats) {
3471356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // TODO(jessehall): Fill out the set of supported formats. Longer term, add
3481356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // a new gralloc method to query whether a (format, usage) pair is
3491356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // supported, and check that for each gralloc format that corresponds to a
3501356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // Vulkan format. Shorter term, just add a few more formats to the ones
3511356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // hardcoded below.
352d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
353d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const VkSurfaceFormatKHR kFormats[] = {
3542676338dd692b7d1e1c276d82e6b0492db53ab2eJesse Hall        {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
3552676338dd692b7d1e1c276d82e6b0492db53ab2eJesse Hall        {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
3562676338dd692b7d1e1c276d82e6b0492db53ab2eJesse Hall        {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
357d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
358d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
359d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
360d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
361d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (formats) {
362d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (*count < kNumFormats)
363d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            result = VK_INCOMPLETE;
364d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        std::copy(kFormats, kFormats + std::min(*count, kNumFormats), formats);
365d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
366d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *count = kNumFormats;
367d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return result;
368b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
369b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
370e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
371622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice /*pdev*/,
372622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                                 VkSurfaceKHR /*surface*/,
373622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                                 uint32_t* count,
374622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                                 VkPresentModeKHR* modes) {
375d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const VkPresentModeKHR kModes[] = {
376d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR,
377d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
378d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const uint32_t kNumModes = sizeof(kModes) / sizeof(kModes[0]);
379d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
380d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
381d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (modes) {
382d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (*count < kNumModes)
383d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            result = VK_INCOMPLETE;
384d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        std::copy(kModes, kModes + std::min(*count, kNumModes), modes);
385d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
386d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *count = kNumModes;
387d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return result;
388b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
389b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
390e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
391622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult CreateSwapchainKHR(VkDevice device,
392622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                            const VkSwapchainCreateInfoKHR* create_info,
393622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                            const VkAllocationCallbacks* allocator,
394622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                            VkSwapchainKHR* swapchain_handle) {
395d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int err;
396d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
397d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
3983d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
3993d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          " minImageCount=%u imageFormat=%u imageColorSpace=%u"
4003d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
4013d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          " oldSwapchain=0x%" PRIx64,
4023d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          reinterpret_cast<uint64_t>(create_info->surface),
4033d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          create_info->minImageCount, create_info->imageFormat,
4043d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          create_info->imageColorSpace, create_info->imageExtent.width,
4053d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          create_info->imageExtent.height, create_info->imageUsage,
4063d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          create_info->preTransform, create_info->presentMode,
4073d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          reinterpret_cast<uint64_t>(create_info->oldSwapchain));
4083d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
4091f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    if (!allocator)
4104a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu        allocator = &GetData(device).allocator;
4111f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall
41242a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ALOGV_IF(create_info->imageArrayLayers != 1,
413dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "swapchain imageArrayLayers=%u not supported",
414715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall             create_info->imageArrayLayers);
41542a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ALOGV_IF(create_info->imageColorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
416dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "swapchain imageColorSpace=%u not supported",
417dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             create_info->imageColorSpace);
41842a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ALOGV_IF((create_info->preTransform & ~kSupportedTransforms) != 0,
419dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "swapchain preTransform=%#x not supported",
42055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall             create_info->preTransform);
42142a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ALOGV_IF(!(create_info->presentMode == VK_PRESENT_MODE_FIFO_KHR ||
4220ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall               create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR),
423dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "swapchain presentMode=%u not supported",
4240ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall             create_info->presentMode);
425d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
4263d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    Surface& surface = *SurfaceFromHandle(create_info->surface);
4273d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
428dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (surface.swapchain_handle != create_info->oldSwapchain) {
42942a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall        ALOGV("Can't create a swapchain for VkSurfaceKHR 0x%" PRIx64
430dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              " because it already has active swapchain 0x%" PRIx64
431dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              " but VkSwapchainCreateInfo::oldSwapchain=0x%" PRIx64,
432dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              reinterpret_cast<uint64_t>(create_info->surface),
433dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              reinterpret_cast<uint64_t>(surface.swapchain_handle),
434dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              reinterpret_cast<uint64_t>(create_info->oldSwapchain));
435dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
436dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
437dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (create_info->oldSwapchain != VK_NULL_HANDLE)
438dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        OrphanSwapchain(device, SwapchainFromHandle(create_info->oldSwapchain));
439dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
4403d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // -- Reset the native window --
4413d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // The native window might have been used previously, and had its properties
4423d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // changed from defaults. That will affect the answer we get for queries
4433d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we
4443d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // attempt such queries.
4453d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
446dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // The native window only allows dequeueing all buffers before any have
447dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // been queued, since after that point at least one is assumed to be in
448dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // non-FREE state at any given time. Disconnecting and re-connecting
449dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // orphans the previous buffers, getting us back to the state where we can
450dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // dequeue all buffers.
451dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    err = native_window_api_disconnect(surface.window.get(),
452dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                                       NATIVE_WINDOW_API_EGL);
453dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)",
454dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             strerror(-err), err);
455dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    err =
456dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        native_window_api_connect(surface.window.get(), NATIVE_WINDOW_API_EGL);
457dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOGW_IF(err != 0, "native_window_api_connect failed: %s (%d)",
458dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             strerror(-err), err);
459dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
4603d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    err = native_window_set_buffer_count(surface.window.get(), 0);
4613d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    if (err != 0) {
4623d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
4633d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall              strerror(-err), err);
4643d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
4653d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    }
4663d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
4673d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    err = surface.window->setSwapInterval(surface.window.get(), 1);
4683d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    if (err != 0) {
4693d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
4703d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        // errors and translate them to valid Vulkan result codes?
4713d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
4723d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall              strerror(-err), err);
4733d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
4743d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    }
4753d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
476d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Configure the native window --
477d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
4784a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu    const auto& dispatch = GetData(device).driver;
47970f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall
480517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    int native_format = HAL_PIXEL_FORMAT_RGBA_8888;
481517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    switch (create_info->imageFormat) {
482517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        case VK_FORMAT_R8G8B8A8_UNORM:
483517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        case VK_FORMAT_R8G8B8A8_SRGB:
484517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall            native_format = HAL_PIXEL_FORMAT_RGBA_8888;
485517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall            break;
486517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        case VK_FORMAT_R5G6B5_UNORM_PACK16:
487517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall            native_format = HAL_PIXEL_FORMAT_RGB_565;
488517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall            break;
489517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        default:
49042a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall            ALOGV("unsupported swapchain format %d", create_info->imageFormat);
491517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall            break;
492517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    }
493517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    err = native_window_set_buffers_format(surface.window.get(), native_format);
494517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    if (err != 0) {
495517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
496517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        // errors and translate them to valid Vulkan result codes?
497517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
498517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall              native_format, strerror(-err), err);
499517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
500517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    }
501517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    err = native_window_set_buffers_data_space(surface.window.get(),
502517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall                                               HAL_DATASPACE_SRGB_LINEAR);
503517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    if (err != 0) {
504517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
505517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        // errors and translate them to valid Vulkan result codes?
506517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
507517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall              HAL_DATASPACE_SRGB_LINEAR, strerror(-err), err);
508517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
509517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    }
510517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall
5113dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall    err = native_window_set_buffers_dimensions(
5123dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall        surface.window.get(), static_cast<int>(create_info->imageExtent.width),
5133dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall        static_cast<int>(create_info->imageExtent.height));
514d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
515d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
516d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
517d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
518d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              create_info->imageExtent.width, create_info->imageExtent.height,
519d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              strerror(-err), err);
5205ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
521d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
522d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
523178b69664a5f56470c143b5930162f285adc83faJesse Hall    // VkSwapchainCreateInfo::preTransform indicates the transformation the app
524178b69664a5f56470c143b5930162f285adc83faJesse Hall    // applied during rendering. native_window_set_transform() expects the
525178b69664a5f56470c143b5930162f285adc83faJesse Hall    // inverse: the transform the app is requesting that the compositor perform
526178b69664a5f56470c143b5930162f285adc83faJesse Hall    // during composition. With native windows, pre-transform works by rendering
527178b69664a5f56470c143b5930162f285adc83faJesse Hall    // with the same transform the compositor is applying (as in Vulkan), but
528178b69664a5f56470c143b5930162f285adc83faJesse Hall    // then requesting the inverse transform, so that when the compositor does
529178b69664a5f56470c143b5930162f285adc83faJesse Hall    // it's job the two transforms cancel each other out and the compositor ends
530178b69664a5f56470c143b5930162f285adc83faJesse Hall    // up applying an identity transform to the app's buffer.
531178b69664a5f56470c143b5930162f285adc83faJesse Hall    err = native_window_set_buffers_transform(
532178b69664a5f56470c143b5930162f285adc83faJesse Hall        surface.window.get(),
533178b69664a5f56470c143b5930162f285adc83faJesse Hall        InvertTransformToNative(create_info->preTransform));
534178b69664a5f56470c143b5930162f285adc83faJesse Hall    if (err != 0) {
535178b69664a5f56470c143b5930162f285adc83faJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
536178b69664a5f56470c143b5930162f285adc83faJesse Hall        // errors and translate them to valid Vulkan result codes?
537178b69664a5f56470c143b5930162f285adc83faJesse Hall        ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
538178b69664a5f56470c143b5930162f285adc83faJesse Hall              InvertTransformToNative(create_info->preTransform),
539178b69664a5f56470c143b5930162f285adc83faJesse Hall              strerror(-err), err);
540178b69664a5f56470c143b5930162f285adc83faJesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
541178b69664a5f56470c143b5930162f285adc83faJesse Hall    }
542178b69664a5f56470c143b5930162f285adc83faJesse Hall
543f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall    err = native_window_set_scaling_mode(
5441356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
545f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall    if (err != 0) {
546f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
547f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        // errors and translate them to valid Vulkan result codes?
548f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
549f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall              strerror(-err), err);
550f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
551f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall    }
552f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall
553e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall    int query_value;
554e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall    err = surface.window->query(surface.window.get(),
555e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall                                NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
556e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall                                &query_value);
557e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall    if (err != 0 || query_value < 0) {
558d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
559d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
560e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
561e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall              query_value);
5625ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
563d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
564e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall    uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
5650ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall    // The MIN_UNDEQUEUED_BUFFERS query doesn't know whether we'll be using
5660ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall    // async mode or not, and assumes not. But in async mode, the BufferQueue
5670ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall    // requires an extra undequeued buffer.
5680ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall    // See BufferQueueCore::getMinUndequeuedBufferCountLocked().
5690ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall    if (create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR)
5700ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall        min_undequeued_buffers += 1;
5710ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall
572d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t num_images =
573d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        (create_info->minImageCount - 1) + min_undequeued_buffers;
5741356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    err = native_window_set_buffer_count(surface.window.get(), num_images);
575d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
576d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
577d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
5783d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
5793d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall              strerror(-err), err);
5805ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
581d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
582d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
58370f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    int gralloc_usage = 0;
58470f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    // TODO(jessehall): Remove conditional once all drivers have been updated
5851f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    if (dispatch.GetSwapchainGrallocUsageANDROID) {
5861f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall        result = dispatch.GetSwapchainGrallocUsageANDROID(
587f4ab2b18391ab5045b44af9ea1d5698af7c2a0cdJesse Hall            device, create_info->imageFormat, create_info->imageUsage,
58870f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall            &gralloc_usage);
58970f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        if (result != VK_SUCCESS) {
59070f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall            ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
59170f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall            return VK_ERROR_INITIALIZATION_FAILED;
59270f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        }
59370f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    } else {
59470f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        gralloc_usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
59570f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    }
5961356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    err = native_window_set_usage(surface.window.get(), gralloc_usage);
59770f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    if (err != 0) {
59870f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
59970f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        // errors and translate them to valid Vulkan result codes?
60070f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
60170f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
60270f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    }
603d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
6043d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    int swap_interval =
6053d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
6063d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
6070ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall    if (err != 0) {
6080ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
6090ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall        // errors and translate them to valid Vulkan result codes?
6103d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        ALOGE("native_window->setSwapInterval(%d) failed: %s (%d)",
6113d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall              swap_interval, strerror(-err), err);
6120ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
6130ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall    }
6140ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall
615d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Allocate our Swapchain object --
616d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // After this point, we must deallocate the swapchain on error.
617d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
6181f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    void* mem = allocator->pfnAllocation(allocator->pUserData,
6191f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                                         sizeof(Swapchain), alignof(Swapchain),
6201f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
6211356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (!mem)
622d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return VK_ERROR_OUT_OF_HOST_MEMORY;
6231356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Swapchain* swapchain = new (mem) Swapchain(surface, num_images);
624d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
625d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Dequeue all buffers and create a VkImage for each --
626d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // Any failures during or after this must cancel the dequeued buffers.
627d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
628d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkNativeBufferANDROID image_native_buffer = {
629d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic push
630d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wold-style-cast"
631d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
632d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic pop
633d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .pNext = nullptr,
634d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
635d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkImageCreateInfo image_create = {
636d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
637d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .pNext = &image_native_buffer,
638d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .imageType = VK_IMAGE_TYPE_2D,
639517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        .format = create_info->imageFormat,
640d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .extent = {0, 0, 1},
641d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .mipLevels = 1,
642a15a4bf4bafd6114ae8f28c2df2fc622cb3baaceJesse Hall        .arrayLayers = 1,
643091ed9e69400edcc549c9b11635d1a305d6b5a83Jesse Hall        .samples = VK_SAMPLE_COUNT_1_BIT,
644d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .tiling = VK_IMAGE_TILING_OPTIMAL,
645f4ab2b18391ab5045b44af9ea1d5698af7c2a0cdJesse Hall        .usage = create_info->imageUsage,
646d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .flags = 0,
647f4ab2b18391ab5045b44af9ea1d5698af7c2a0cdJesse Hall        .sharingMode = create_info->imageSharingMode,
64803b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall        .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
649d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
650d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
651d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
652d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (uint32_t i = 0; i < num_images; i++) {
653d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Swapchain::Image& img = swapchain->images[i];
654d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
655d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ANativeWindowBuffer* buffer;
6561356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        err = surface.window->dequeueBuffer(surface.window.get(), &buffer,
6571356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall                                            &img.dequeue_fence);
658d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (err != 0) {
659d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // TODO(jessehall): Improve error reporting. Can we enumerate
660d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // possible errors and translate them to valid Vulkan result codes?
661d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
6625ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall            result = VK_ERROR_INITIALIZATION_FAILED;
663d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            break;
664d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
665e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu        img.buffer = buffer;
666d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        img.dequeued = true;
667d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
668d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_create.extent =
6693dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall            VkExtent3D{static_cast<uint32_t>(img.buffer->width),
6703dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall                       static_cast<uint32_t>(img.buffer->height),
6713dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall                       1};
672d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.handle = img.buffer->handle;
673d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.stride = img.buffer->stride;
674d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.format = img.buffer->format;
675d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.usage = img.buffer->usage;
676d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
67703b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall        result =
6781f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall            dispatch.CreateImage(device, &image_create, nullptr, &img.image);
679d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (result != VK_SUCCESS) {
680d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGD("vkCreateImage w/ native buffer failed: %u", result);
681d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            break;
682d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
683d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
684d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
685d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Cancel all buffers, returning them to the queue --
686d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // If an error occurred before, also destroy the VkImage and release the
687d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // buffer reference. Otherwise, we retain a strong reference to the buffer.
688d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    //
689d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): The error path here is the same as DestroySwapchain,
690d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // but not the non-error path. Should refactor/unify.
691d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (uint32_t i = 0; i < num_images; i++) {
692d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Swapchain::Image& img = swapchain->images[i];
693d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (img.dequeued) {
6941356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall            surface.window->cancelBuffer(surface.window.get(), img.buffer.get(),
6951356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall                                         img.dequeue_fence);
696d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            img.dequeue_fence = -1;
697d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            img.dequeued = false;
698d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
699d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (result != VK_SUCCESS) {
700d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            if (img.image)
7011f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                dispatch.DestroyImage(device, img.image, nullptr);
702d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
703d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
704d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
705d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (result != VK_SUCCESS) {
706d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        swapchain->~Swapchain();
7071f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall        allocator->pfnFree(allocator->pUserData, swapchain);
708d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return result;
709d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
710d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
711dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    surface.swapchain_handle = HandleFromSwapchain(swapchain);
712dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    *swapchain_handle = surface.swapchain_handle;
713b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
714b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
715b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
716e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
717622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wuvoid DestroySwapchainKHR(VkDevice device,
718622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                         VkSwapchainKHR swapchain_handle,
719622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                         const VkAllocationCallbacks* allocator) {
7204a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu    const auto& dispatch = GetData(device).driver;
721d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
72242a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    bool active = swapchain->surface.swapchain_handle == swapchain_handle;
72342a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
724dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
725dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    for (uint32_t i = 0; i < swapchain->num_images; i++)
726dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
72742a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    if (active)
728dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
7291f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    if (!allocator)
7304a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu        allocator = &GetData(device).allocator;
731d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    swapchain->~Swapchain();
7321f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    allocator->pfnFree(allocator->pUserData, swapchain);
733b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
734b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
735e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
736622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult GetSwapchainImagesKHR(VkDevice,
737622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                               VkSwapchainKHR swapchain_handle,
738622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                               uint32_t* count,
739622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                               VkImage* images) {
740d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
741dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOGW_IF(swapchain.surface.swapchain_handle != swapchain_handle,
742dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "getting images for non-active swapchain 0x%" PRIx64
743dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "; only dequeued image handles are valid",
744dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             reinterpret_cast<uint64_t>(swapchain_handle));
745d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
746d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (images) {
747d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        uint32_t n = swapchain.num_images;
748d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (*count < swapchain.num_images) {
749d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            n = *count;
750d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            result = VK_INCOMPLETE;
751d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
752d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        for (uint32_t i = 0; i < n; i++)
753d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            images[i] = swapchain.images[i].image;
754d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
755d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *count = swapchain.num_images;
756d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return result;
757b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
758b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
759e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
760622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult AcquireNextImageKHR(VkDevice device,
761622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             VkSwapchainKHR swapchain_handle,
762622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             uint64_t timeout,
763622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             VkSemaphore semaphore,
764622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             VkFence vk_fence,
765622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             uint32_t* image_index) {
766d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
7671356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    ANativeWindow* window = swapchain.surface.window.get();
768d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result;
769d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int err;
770d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
771dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (swapchain.surface.swapchain_handle != swapchain_handle)
772dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        return VK_ERROR_OUT_OF_DATE_KHR;
773dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
774d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGW_IF(
775d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        timeout != UINT64_MAX,
776d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented");
777d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
778d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ANativeWindowBuffer* buffer;
779061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall    int fence_fd;
780061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall    err = window->dequeueBuffer(window, &buffer, &fence_fd);
781d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
782d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
783d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
784d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
7855ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        return VK_ERROR_INITIALIZATION_FAILED;
786d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
787d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
788d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t idx;
789d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (idx = 0; idx < swapchain.num_images; idx++) {
790d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (swapchain.images[idx].buffer.get() == buffer) {
791d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            swapchain.images[idx].dequeued = true;
792061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall            swapchain.images[idx].dequeue_fence = fence_fd;
793d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            break;
794d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
795d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
796d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (idx == swapchain.num_images) {
797d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("dequeueBuffer returned unrecognized buffer");
798061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall        window->cancelBuffer(window, buffer, fence_fd);
799d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return VK_ERROR_OUT_OF_DATE_KHR;
800d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
801d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
802d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int fence_clone = -1;
803061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall    if (fence_fd != -1) {
804061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall        fence_clone = dup(fence_fd);
805d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (fence_clone == -1) {
806d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGE("dup(fence) failed, stalling until signalled: %s (%d)",
807d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                  strerror(errno), errno);
808061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall            sync_wait(fence_fd, -1 /* forever */);
809d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
810d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
811d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
8124a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu    result = GetData(device).driver.AcquireImageANDROID(
8131f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall        device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence);
814d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (result != VK_SUCCESS) {
815ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // NOTE: we're relying on AcquireImageANDROID to close fence_clone,
816ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // even if the call fails. We could close it ourselves on failure, but
817ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // that would create a race condition if the driver closes it on a
818ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // failure path: some other thread might create an fd with the same
819ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // number between the time the driver closes it and the time we close
820ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // it. We must assume one of: the driver *always* closes it even on
821ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // failure, or *never* closes it on failure.
822061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall        window->cancelBuffer(window, buffer, fence_fd);
823d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        swapchain.images[idx].dequeued = false;
824d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        swapchain.images[idx].dequeue_fence = -1;
825d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return result;
826d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
827d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
828d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *image_index = idx;
829b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
830b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
831b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
832dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hallstatic VkResult WorstPresentResult(VkResult a, VkResult b) {
833dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // See the error ranking for vkQueuePresentKHR at the end of section 29.6
834dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // (in spec version 1.0.14).
835dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    static const VkResult kWorstToBest[] = {
836dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_DEVICE_LOST,
837dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_SURFACE_LOST_KHR,
838dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_OUT_OF_DATE_KHR,
839dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_OUT_OF_DEVICE_MEMORY,
840dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_OUT_OF_HOST_MEMORY,
841dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_SUBOPTIMAL_KHR,
842dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    };
843dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    for (auto result : kWorstToBest) {
844dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (a == result || b == result)
845dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            return result;
846dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
847dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOG_ASSERT(a == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", a);
848dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOG_ASSERT(b == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", b);
849dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    return a != VK_SUCCESS ? a : b;
850dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall}
851dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
852e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
853622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
854d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
855d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
856d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             present_info->sType);
857d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGV_IF(present_info->pNext, "VkPresentInfo::pNext != NULL");
858d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
859dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    VkDevice device = GetData(queue).driver_device;
8604a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu    const auto& dispatch = GetData(queue).driver;
861d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult final_result = VK_SUCCESS;
862dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
863d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
864d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Swapchain& swapchain =
86503b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall            *SwapchainFromHandle(present_info->pSwapchains[sc]);
866f4ab2b18391ab5045b44af9ea1d5698af7c2a0cdJesse Hall        uint32_t image_idx = present_info->pImageIndices[sc];
8675ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        Swapchain::Image& img = swapchain.images[image_idx];
868dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VkResult swapchain_result = VK_SUCCESS;
869d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VkResult result;
870d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        int err;
871d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
872d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        int fence = -1;
873275d76c8158c90ec5317b82cb10b094bca2b43cfJesse Hall        result = dispatch.QueueSignalReleaseImageANDROID(
874275d76c8158c90ec5317b82cb10b094bca2b43cfJesse Hall            queue, present_info->waitSemaphoreCount,
875275d76c8158c90ec5317b82cb10b094bca2b43cfJesse Hall            present_info->pWaitSemaphores, img.image, &fence);
876d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (result != VK_SUCCESS) {
877ab9aeef063119445b59166f781c464c64e3909dbJesse Hall            ALOGE("QueueSignalReleaseImageANDROID failed: %d", result);
878dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            swapchain_result = result;
879d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
880d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
881dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (swapchain.surface.swapchain_handle ==
882dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            present_info->pSwapchains[sc]) {
883dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            ANativeWindow* window = swapchain.surface.window.get();
884dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            if (swapchain_result == VK_SUCCESS) {
885dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                err = window->queueBuffer(window, img.buffer.get(), fence);
886dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                // queueBuffer always closes fence, even on error
887dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                if (err != 0) {
888dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    // TODO(jessehall): What now? We should probably cancel the
889dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    // buffer, I guess?
890dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
891dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    swapchain_result = WorstPresentResult(
892dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                        swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
893dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                }
894dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                if (img.dequeue_fence >= 0) {
895dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    close(img.dequeue_fence);
896dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    img.dequeue_fence = -1;
897dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                }
898dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                img.dequeued = false;
899dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            }
900dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            if (swapchain_result != VK_SUCCESS) {
901dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                ReleaseSwapchainImage(device, window, fence, img);
902dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                OrphanSwapchain(device, &swapchain);
903dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            }
904dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        } else {
905dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            ReleaseSwapchainImage(device, nullptr, fence, img);
906dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            swapchain_result = VK_ERROR_OUT_OF_DATE_KHR;
907d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
908d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
909a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall        if (present_info->pResults)
910dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            present_info->pResults[sc] = swapchain_result;
911dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
912dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (swapchain_result != final_result)
913dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            final_result = WorstPresentResult(final_result, swapchain_result);
914d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
915d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
916d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return final_result;
917d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
918b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
919622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu}  // namespace driver
920b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}  // namespace vulkan
921