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
197992781a574b1c52a203e9271772da16f0f06812Jesse Hall#include <grallocusage/GrallocUsageConversion.h>
207823e124e00576e20e47ec717cbe8bc89f0f2bf2Mark Salyzyn#include <log/log.h>
216e1193af40c870c50013affec37c8429986b3c7bPawin Vongmasa#include <ui/BufferQueueDefs.h>
22d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <sync/sync.h>
23e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu#include <utils/StrongPointer.h>
241049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson#include <utils/Vector.h>
25d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
264a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu#include "driver.h"
27d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
285ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// TODO(jessehall): Currently we don't have a good error code for when a native
295ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// window operation fails. Just returning INITIALIZATION_FAILED for now. Later
305ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// versions (post SDK 0.9) of the API/extension have a better error code.
315ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// When updating to that version, audit all error returns.
32622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wunamespace vulkan {
33622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wunamespace driver {
345ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall
35d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallnamespace {
36d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
3755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hallconst VkSurfaceTransformFlagsKHR kSupportedTransforms =
3855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR |
3955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
4055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR |
4155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR |
4255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
4355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
4455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
4555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
4655bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
4755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
4855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
4955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse HallVkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) {
5055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // Native and Vulkan transforms are isomorphic, but are represented
5155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // differently. Vulkan transforms are built up of an optional horizontal
5255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // mirror, followed by a clockwise 0/90/180/270-degree rotation. Native
5355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // transforms are built up from a horizontal flip, vertical flip, and
5455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // 90-degree rotation, all optional but always in that order.
5555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
5655bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // TODO(jessehall): For now, only support pure rotations, not
5755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // flip or flip-and-rotate, until I have more time to test them and build
5855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // sample code. As far as I know we never actually use anything besides
5955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    // pure rotations anyway.
6055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
6155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    switch (native) {
6255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case 0:  // 0x0
6355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
6455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        // case NATIVE_WINDOW_TRANSFORM_FLIP_H:  // 0x1
6555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
6655bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        // case NATIVE_WINDOW_TRANSFORM_FLIP_V:  // 0x2
6755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
6855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case NATIVE_WINDOW_TRANSFORM_ROT_180:  // FLIP_H | FLIP_V
6955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
7055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case NATIVE_WINDOW_TRANSFORM_ROT_90:  // 0x4
7155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
7255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        // case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
7355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
7455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        // case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
7555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
7655bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case NATIVE_WINDOW_TRANSFORM_ROT_270:  // FLIP_H | FLIP_V | ROT_90
7755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
7855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
7955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        default:
8055bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall            return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
8155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    }
8255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall}
8355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
84178b69664a5f56470c143b5930162f285adc83faJesse Hallint InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) {
85178b69664a5f56470c143b5930162f285adc83faJesse Hall    switch (transform) {
86178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
87178b69664a5f56470c143b5930162f285adc83faJesse Hall            return NATIVE_WINDOW_TRANSFORM_ROT_270;
88178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
89178b69664a5f56470c143b5930162f285adc83faJesse Hall            return NATIVE_WINDOW_TRANSFORM_ROT_180;
90178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
91178b69664a5f56470c143b5930162f285adc83faJesse Hall            return NATIVE_WINDOW_TRANSFORM_ROT_90;
92178b69664a5f56470c143b5930162f285adc83faJesse Hall        // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
93178b69664a5f56470c143b5930162f285adc83faJesse Hall        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
94178b69664a5f56470c143b5930162f285adc83faJesse Hall        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H;
95178b69664a5f56470c143b5930162f285adc83faJesse Hall        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
96178b69664a5f56470c143b5930162f285adc83faJesse Hall        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H |
97178b69664a5f56470c143b5930162f285adc83faJesse Hall        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
98178b69664a5f56470c143b5930162f285adc83faJesse Hall        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
99178b69664a5f56470c143b5930162f285adc83faJesse Hall        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V;
100178b69664a5f56470c143b5930162f285adc83faJesse Hall        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
101178b69664a5f56470c143b5930162f285adc83faJesse Hall        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V |
102178b69664a5f56470c143b5930162f285adc83faJesse Hall        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
103178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
104178b69664a5f56470c143b5930162f285adc83faJesse Hall        case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
105178b69664a5f56470c143b5930162f285adc83faJesse Hall        default:
106178b69664a5f56470c143b5930162f285adc83faJesse Hall            return 0;
107178b69664a5f56470c143b5930162f285adc83faJesse Hall    }
108178b69664a5f56470c143b5930162f285adc83faJesse Hall}
109178b69664a5f56470c143b5930162f285adc83faJesse Hall
1108a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliottclass TimingInfo {
1118a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott   public:
1121049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    TimingInfo() = default;
1131049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId)
1142c6355d7a54cb24db3f790e8c9e05fad897a6aecIan Elliott        : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
1151049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson          native_frame_id_(nativeFrameId) {}
1161049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    bool ready() const {
117dc96fdfa58260867c993fff78611220874753201Brian Anderson        return (timestamp_desired_present_time_ !=
118dc96fdfa58260867c993fff78611220874753201Brian Anderson                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
119dc96fdfa58260867c993fff78611220874753201Brian Anderson                timestamp_actual_present_time_ !=
120dc96fdfa58260867c993fff78611220874753201Brian Anderson                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
121dc96fdfa58260867c993fff78611220874753201Brian Anderson                timestamp_render_complete_time_ !=
122dc96fdfa58260867c993fff78611220874753201Brian Anderson                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
123dc96fdfa58260867c993fff78611220874753201Brian Anderson                timestamp_composition_latch_time_ !=
124dc96fdfa58260867c993fff78611220874753201Brian Anderson                        NATIVE_WINDOW_TIMESTAMP_PENDING);
1258a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    }
126dc96fdfa58260867c993fff78611220874753201Brian Anderson    void calculate(int64_t rdur) {
127dc96fdfa58260867c993fff78611220874753201Brian Anderson        bool anyTimestampInvalid =
128dc96fdfa58260867c993fff78611220874753201Brian Anderson                (timestamp_actual_present_time_ ==
129dc96fdfa58260867c993fff78611220874753201Brian Anderson                        NATIVE_WINDOW_TIMESTAMP_INVALID) ||
130dc96fdfa58260867c993fff78611220874753201Brian Anderson                (timestamp_render_complete_time_ ==
131dc96fdfa58260867c993fff78611220874753201Brian Anderson                        NATIVE_WINDOW_TIMESTAMP_INVALID) ||
132dc96fdfa58260867c993fff78611220874753201Brian Anderson                (timestamp_composition_latch_time_ ==
133dc96fdfa58260867c993fff78611220874753201Brian Anderson                        NATIVE_WINDOW_TIMESTAMP_INVALID);
134dc96fdfa58260867c993fff78611220874753201Brian Anderson        if (anyTimestampInvalid) {
135dc96fdfa58260867c993fff78611220874753201Brian Anderson            ALOGE("Unexpectedly received invalid timestamp.");
136dc96fdfa58260867c993fff78611220874753201Brian Anderson            vals_.actualPresentTime = 0;
137dc96fdfa58260867c993fff78611220874753201Brian Anderson            vals_.earliestPresentTime = 0;
138dc96fdfa58260867c993fff78611220874753201Brian Anderson            vals_.presentMargin = 0;
139dc96fdfa58260867c993fff78611220874753201Brian Anderson            return;
140dc96fdfa58260867c993fff78611220874753201Brian Anderson        }
141dc96fdfa58260867c993fff78611220874753201Brian Anderson
142dc96fdfa58260867c993fff78611220874753201Brian Anderson        vals_.actualPresentTime =
143dc96fdfa58260867c993fff78611220874753201Brian Anderson                static_cast<uint64_t>(timestamp_actual_present_time_);
144dc96fdfa58260867c993fff78611220874753201Brian Anderson        int64_t margin = (timestamp_composition_latch_time_ -
1458a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                           timestamp_render_complete_time_);
1468a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // Calculate vals_.earliestPresentTime, and potentially adjust
1478a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // vals_.presentMargin.  The initial value of vals_.earliestPresentTime
1488a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // is vals_.actualPresentTime.  If we can subtract rdur (the duration
1498a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // of a refresh cycle) from vals_.earliestPresentTime (and also from
1508a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // vals_.presentMargin) and still leave a positive margin, then we can
1518a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // report to the application that it could have presented earlier than
1528a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // it did (per the extension specification).  If for some reason, we
1538a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // can do this subtraction repeatedly, we do, since
1548a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // vals_.earliestPresentTime really is supposed to be the "earliest".
155dc96fdfa58260867c993fff78611220874753201Brian Anderson        int64_t early_time = timestamp_actual_present_time_;
1568a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        while ((margin > rdur) &&
1578a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott               ((early_time - rdur) > timestamp_composition_latch_time_)) {
1588a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott            early_time -= rdur;
1598a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott            margin -= rdur;
1608a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        }
161dc96fdfa58260867c993fff78611220874753201Brian Anderson        vals_.earliestPresentTime = static_cast<uint64_t>(early_time);
162dc96fdfa58260867c993fff78611220874753201Brian Anderson        vals_.presentMargin = static_cast<uint64_t>(margin);
1638a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    }
1641049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    void get_values(VkPastPresentationTimingGOOGLE* values) const {
1651049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        *values = vals_;
1661049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    }
1678a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott
1688a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott   public:
1691049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
1708a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott
1711049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    uint64_t native_frame_id_ { 0 };
172dc96fdfa58260867c993fff78611220874753201Brian Anderson    int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING };
173dc96fdfa58260867c993fff78611220874753201Brian Anderson    int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
174dc96fdfa58260867c993fff78611220874753201Brian Anderson    int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
175dc96fdfa58260867c993fff78611220874753201Brian Anderson    int64_t timestamp_composition_latch_time_
176dc96fdfa58260867c993fff78611220874753201Brian Anderson            { NATIVE_WINDOW_TIMESTAMP_PENDING };
1778a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott};
1788a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott
179d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// ----------------------------------------------------------------------------
180d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1811356b0d3179254a7a27e88abb2d2500385469f14Jesse Hallstruct Surface {
182e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu    android::sp<ANativeWindow> window;
183dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    VkSwapchainKHR swapchain_handle;
1841356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall};
1851356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
1861356b0d3179254a7a27e88abb2d2500385469f14Jesse HallVkSurfaceKHR HandleFromSurface(Surface* surface) {
1871356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface));
1881356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
1891356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
1901356b0d3179254a7a27e88abb2d2500385469f14Jesse HallSurface* SurfaceFromHandle(VkSurfaceKHR handle) {
191a3a7a1d37bdfad56245b75edac49f8aceded321dJesse Hall    return reinterpret_cast<Surface*>(handle);
1921356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
1931356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
1948a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott// Maximum number of TimingInfo structs to keep per swapchain:
1958a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliottenum { MAX_TIMING_INFOS = 10 };
1968a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott// Minimum number of frames to look for in the past (so we don't cause
1978a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott// syncronous requests to Surface Flinger):
1988a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliottenum { MIN_NUM_FRAMES_AGO = 5 };
1998a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott
200d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallstruct Swapchain {
201ffedb65cea7551bc689552c0bc21343f568d000eIan Elliott    Swapchain(Surface& surface_,
202ffedb65cea7551bc689552c0bc21343f568d000eIan Elliott              uint32_t num_images_,
203ffedb65cea7551bc689552c0bc21343f568d000eIan Elliott              VkPresentModeKHR present_mode)
2044c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott        : surface(surface_),
2054c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott          num_images(num_images_),
206ffedb65cea7551bc689552c0bc21343f568d000eIan Elliott          mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR),
207f883564b397bb97b793ccd04be89e4137ab1acd2Chris Forbes          frame_timestamps_enabled(false),
208f883564b397bb97b793ccd04be89e4137ab1acd2Chris Forbes          shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
209f883564b397bb97b793ccd04be89e4137ab1acd2Chris Forbes                 present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
21062c48c931f88ec44c41621afe988c34cab1fb41dIan Elliott        ANativeWindow* window = surface.window.get();
211be833a27b36149e48f2e1b8bbb2f70dd63428419Ian Elliott        native_window_get_refresh_cycle_duration(
21262c48c931f88ec44c41621afe988c34cab1fb41dIan Elliott            window,
213dc96fdfa58260867c993fff78611220874753201Brian Anderson            &refresh_duration);
2148a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    }
215d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
2161356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface& surface;
217d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t num_images;
218ffedb65cea7551bc689552c0bc21343f568d000eIan Elliott    bool mailbox_mode;
2194c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    bool frame_timestamps_enabled;
220dc96fdfa58260867c993fff78611220874753201Brian Anderson    int64_t refresh_duration;
221f883564b397bb97b793ccd04be89e4137ab1acd2Chris Forbes    bool shared;
222d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
223d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    struct Image {
224d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
225d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VkImage image;
226e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu        android::sp<ANativeWindowBuffer> buffer;
227d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // The fence is only valid when the buffer is dequeued, and should be
228d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // -1 any other time. When valid, we own the fd, and must ensure it is
229d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // closed: either by closing it explicitly when queueing the buffer,
230d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
231d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        int dequeue_fence;
232d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        bool dequeued;
2336e1193af40c870c50013affec37c8429986b3c7bPawin Vongmasa    } images[android::BufferQueueDefs::NUM_BUFFER_SLOTS];
2348a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott
2351049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    android::Vector<TimingInfo> timing;
236d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall};
237d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
238d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallVkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
239d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain));
240d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
241d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
242d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallSwapchain* SwapchainFromHandle(VkSwapchainKHR handle) {
243a3a7a1d37bdfad56245b75edac49f8aceded321dJesse Hall    return reinterpret_cast<Swapchain*>(handle);
244d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
245d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
246dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hallvoid ReleaseSwapchainImage(VkDevice device,
247dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                           ANativeWindow* window,
248dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                           int release_fence,
249dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                           Swapchain::Image& image) {
250dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOG_ASSERT(release_fence == -1 || image.dequeued,
251dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                "ReleaseSwapchainImage: can't provide a release fence for "
252dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                "non-dequeued images");
253dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
254dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (image.dequeued) {
255dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (release_fence >= 0) {
256dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // We get here from vkQueuePresentKHR. The application is
257dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // responsible for creating an execution dependency chain from
258dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // vkAcquireNextImage (dequeue_fence) to vkQueuePresentKHR
259dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // (release_fence), so we can drop the dequeue_fence here.
260dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            if (image.dequeue_fence >= 0)
261dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                close(image.dequeue_fence);
262dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        } else {
263dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // We get here during swapchain destruction, or various serious
264dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // error cases e.g. when we can't create the release_fence during
265dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // vkQueuePresentKHR. In non-error cases, the dequeue_fence should
266dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // have already signalled, since the swapchain images are supposed
267dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // to be idle before the swapchain is destroyed. In error cases,
268dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // there may be rendering in flight to the image, but since we
269dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // weren't able to create a release_fence, waiting for the
270dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            // dequeue_fence is about the best we can do.
271dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            release_fence = image.dequeue_fence;
272dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        }
273dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        image.dequeue_fence = -1;
274dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
275dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (window) {
276dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            window->cancelBuffer(window, image.buffer.get(), release_fence);
277dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        } else {
278dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            if (release_fence >= 0) {
279dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                sync_wait(release_fence, -1 /* forever */);
280dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                close(release_fence);
281dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            }
282dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        }
283dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
284dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        image.dequeued = false;
285dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
286dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
287dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (image.image) {
288dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        GetData(device).driver.DestroyImage(device, image.image, nullptr);
289dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        image.image = VK_NULL_HANDLE;
290dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
291dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
292dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    image.buffer.clear();
293dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall}
294dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
295dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hallvoid OrphanSwapchain(VkDevice device, Swapchain* swapchain) {
296dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (swapchain->surface.swapchain_handle != HandleFromSwapchain(swapchain))
297dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        return;
298dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    for (uint32_t i = 0; i < swapchain->num_images; i++) {
299dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (!swapchain->images[i].dequeued)
300dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            ReleaseSwapchainImage(device, nullptr, -1, swapchain->images[i]);
301dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
302dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
3038a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    swapchain->timing.clear();
3048a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott}
3058a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott
3068a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliottuint32_t get_num_ready_timings(Swapchain& swapchain) {
3071049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    if (swapchain.timing.size() < MIN_NUM_FRAMES_AGO) {
3081049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        return 0;
3091049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    }
3101049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
3118a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    uint32_t num_ready = 0;
3121049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1;
3138a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    for (uint32_t i = 0; i < num_timings; i++) {
3141049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        TimingInfo& ti = swapchain.timing.editItemAt(i);
3151049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        if (ti.ready()) {
3161049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            // This TimingInfo is ready to be reported to the user.  Add it
3171049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            // to the num_ready.
3181049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            num_ready++;
3191049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            continue;
3201049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        }
3211049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        // This TimingInfo is not yet ready to be reported to the user,
3221049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        // and so we should look for any available timestamps that
3231049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        // might make it ready.
3241049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        int64_t desired_present_time = 0;
3251049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        int64_t render_complete_time = 0;
3261049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        int64_t composition_latch_time = 0;
3271049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        int64_t actual_present_time = 0;
3281049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        // Obtain timestamps:
3291049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        int ret = native_window_get_frame_timestamps(
3301049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            swapchain.surface.window.get(), ti.native_frame_id_,
3311049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            &desired_present_time, &render_complete_time,
3321049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            &composition_latch_time,
3331049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            NULL,  //&first_composition_start_time,
3341049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            NULL,  //&last_composition_start_time,
3351049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            NULL,  //&composition_finish_time,
3361049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            // TODO(ianelliott): Maybe ask if this one is
3371049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            // supported, at startup time (since it may not be
3381049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            // supported):
3391049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            &actual_present_time,
3401049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            NULL,  //&dequeue_ready_time,
3411049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            NULL /*&reads_done_time*/);
3421049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
3431049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        if (ret != android::NO_ERROR) {
3441049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            continue;
3451049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        }
3461049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
3471049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        // Record the timestamp(s) we received, and then see if this TimingInfo
3481049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        // is ready to be reported to the user:
349dc96fdfa58260867c993fff78611220874753201Brian Anderson        ti.timestamp_desired_present_time_ = desired_present_time;
350dc96fdfa58260867c993fff78611220874753201Brian Anderson        ti.timestamp_actual_present_time_ = actual_present_time;
351dc96fdfa58260867c993fff78611220874753201Brian Anderson        ti.timestamp_render_complete_time_ = render_complete_time;
352dc96fdfa58260867c993fff78611220874753201Brian Anderson        ti.timestamp_composition_latch_time_ = composition_latch_time;
3531049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
3541049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        if (ti.ready()) {
3551049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            // The TimingInfo has received enough timestamps, and should now
3561049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            // use those timestamps to calculate the info that should be
3571049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            // reported to the user:
3581049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            ti.calculate(swapchain.refresh_duration);
3591049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            num_ready++;
3608a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        }
3618a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    }
3628a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    return num_ready;
3638a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott}
3648a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott
3658a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott// TODO(ianelliott): DEAL WITH RETURN VALUE (e.g. VK_INCOMPLETE)!!!
3668a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliottvoid copy_ready_timings(Swapchain& swapchain,
3678a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                        uint32_t* count,
3688a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                        VkPastPresentationTimingGOOGLE* timings) {
3691049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    if (swapchain.timing.empty()) {
3701049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        *count = 0;
3711049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        return;
3728a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    }
3731049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
3741049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    size_t last_ready = swapchain.timing.size() - 1;
3751049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    while (!swapchain.timing[last_ready].ready()) {
3761049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        if (last_ready == 0) {
3771049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            *count = 0;
3781049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            return;
3791049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        }
3801049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        last_ready--;
3811049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    }
3821049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
3831049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    uint32_t num_copied = 0;
3841049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    size_t num_to_remove = 0;
3851049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) {
3861049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        const TimingInfo& ti = swapchain.timing[i];
3871049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        if (ti.ready()) {
3881049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson            ti.get_values(&timings[num_copied]);
3898a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott            num_copied++;
3908a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        }
3911049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson        num_to_remove++;
3928a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    }
3931049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
3941049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    // Discard old frames that aren't ready if newer frames are ready.
3951049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    // We don't expect to get the timing info for those old frames.
3961049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson    swapchain.timing.removeItemsAt(0, num_to_remove);
3971049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
3988a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott    *count = num_copied;
399dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall}
400dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
4017d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchterandroid_pixel_format GetNativePixelFormat(VkFormat format) {
4027d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    android_pixel_format native_format = HAL_PIXEL_FORMAT_RGBA_8888;
4037d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    switch (format) {
4047d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_FORMAT_R8G8B8A8_UNORM:
4057d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_FORMAT_R8G8B8A8_SRGB:
4067d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            native_format = HAL_PIXEL_FORMAT_RGBA_8888;
4077d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            break;
4087d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_FORMAT_R5G6B5_UNORM_PACK16:
4097d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            native_format = HAL_PIXEL_FORMAT_RGB_565;
4107d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            break;
4117d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_FORMAT_R16G16B16A16_SFLOAT:
4127d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            native_format = HAL_PIXEL_FORMAT_RGBA_FP16;
4137d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            break;
4147d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
4157d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            native_format = HAL_PIXEL_FORMAT_RGBA_1010102;
4167d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            break;
4177d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        default:
4187d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            ALOGV("unsupported swapchain format %d", format);
4197d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            break;
4207d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    }
4217d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    return native_format;
4227d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter}
4237d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter
4247d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchterandroid_dataspace GetNativeDataspace(VkColorSpaceKHR colorspace) {
4257d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    switch (colorspace) {
4267d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR:
4277d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_V0_SRGB;
4287d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT:
4297d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_DISPLAY_P3;
4307d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
4317d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_V0_SCRGB_LINEAR;
4327d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_DCI_P3_LINEAR_EXT:
4337d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_DCI_P3_LINEAR;
4347d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT:
4357d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_DCI_P3;
4367d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_BT709_LINEAR_EXT:
4377d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_V0_SRGB_LINEAR;
4387d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_BT709_NONLINEAR_EXT:
4397d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_V0_SRGB;
440c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter        case VK_COLOR_SPACE_BT2020_LINEAR_EXT:
441c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter            return HAL_DATASPACE_BT2020_LINEAR;
442c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter        case VK_COLOR_SPACE_HDR10_ST2084_EXT:
4437d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return static_cast<android_dataspace>(
444c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter                HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
445c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter                HAL_DATASPACE_RANGE_FULL);
446c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter        case VK_COLOR_SPACE_DOLBYVISION_EXT:
4477d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return static_cast<android_dataspace>(
4487d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter                HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
4497d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter                HAL_DATASPACE_RANGE_FULL);
450c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter        case VK_COLOR_SPACE_HDR10_HLG_EXT:
451c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter            return static_cast<android_dataspace>(
452c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter                HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_HLG |
453c45673f8f14ecbcf49683ef7dd62dd4123a57fe5Courtney Goeltzenleuchter                HAL_DATASPACE_RANGE_FULL);
4547d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT:
4557d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return static_cast<android_dataspace>(
4567d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter                HAL_DATASPACE_STANDARD_ADOBE_RGB |
4577d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter                HAL_DATASPACE_TRANSFER_LINEAR | HAL_DATASPACE_RANGE_FULL);
4587d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT:
4597d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_ADOBE_RGB;
4607d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter
4617d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        // Pass through is intended to allow app to provide data that is passed
4627d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        // to the display system without modification.
4637d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        case VK_COLOR_SPACE_PASS_THROUGH_EXT:
4647d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_ARBITRARY;
4657d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter
4667d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        default:
4677d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            // This indicates that we don't know about the
4687d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            // dataspace specified and we should indicate that
4697d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            // it's unsupported
4707d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            return HAL_DATASPACE_UNKNOWN;
4717d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    }
4727d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter}
4737d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter
474d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}  // anonymous namespace
475b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
476e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
477622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult CreateAndroidSurfaceKHR(
478f9fa9a50d5e87dacce36ef2a56b392fc053cf8ceJesse Hall    VkInstance instance,
479f9fa9a50d5e87dacce36ef2a56b392fc053cf8ceJesse Hall    const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
480f9fa9a50d5e87dacce36ef2a56b392fc053cf8ceJesse Hall    const VkAllocationCallbacks* allocator,
481f9fa9a50d5e87dacce36ef2a56b392fc053cf8ceJesse Hall    VkSurfaceKHR* out_surface) {
4821f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    if (!allocator)
4834a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu        allocator = &GetData(instance).allocator;
4841f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Surface),
4851f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                                         alignof(Surface),
4861f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
4871356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (!mem)
4881356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        return VK_ERROR_OUT_OF_HOST_MEMORY;
4891356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface* surface = new (mem) Surface;
490b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
491e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu    surface->window = pCreateInfo->window;
492dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    surface->swapchain_handle = VK_NULL_HANDLE;
493b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
4941356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
4951356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    int err =
4961356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
4971356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (err != 0) {
4981356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
4991356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        // errors and translate them to valid Vulkan result codes?
5001356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
5011356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall              err);
5021356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        surface->~Surface();
5031f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall        allocator->pfnFree(allocator->pUserData, surface);
504762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
5051356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    }
506b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
5071356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    *out_surface = HandleFromSurface(surface);
508b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
509b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
510b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
511e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
512622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wuvoid DestroySurfaceKHR(VkInstance instance,
513622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                       VkSurfaceKHR surface_handle,
514622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                       const VkAllocationCallbacks* allocator) {
5151356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    Surface* surface = SurfaceFromHandle(surface_handle);
5161356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (!surface)
5171356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        return;
5181356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL);
51942a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ALOGV_IF(surface->swapchain_handle != VK_NULL_HANDLE,
520dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "destroyed VkSurfaceKHR 0x%" PRIx64
521dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             " has active VkSwapchainKHR 0x%" PRIx64,
522dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             reinterpret_cast<uint64_t>(surface_handle),
523dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             reinterpret_cast<uint64_t>(surface->swapchain_handle));
5241356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    surface->~Surface();
5251f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    if (!allocator)
5264a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu        allocator = &GetData(instance).allocator;
5271f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    allocator->pfnFree(allocator->pUserData, surface);
5281356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
5291356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
530e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
531622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
532622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            uint32_t /*queue_family*/,
533622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            VkSurfaceKHR /*surface*/,
534622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            VkBool32* supported) {
5350e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall    *supported = VK_TRUE;
536a64292517b1876c4bbe5d3e62c577812f40bd922Jesse Hall    return VK_SUCCESS;
5371356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}
5381356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall
539e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
540622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
541b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    VkPhysicalDevice /*pdev*/,
542b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    VkSurfaceKHR surface,
543b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    VkSurfaceCapabilitiesKHR* capabilities) {
544d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int err;
5451356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
546d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
547d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int width, height;
548d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
549d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
550d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
551d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              strerror(-err), err);
552762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
553d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
554d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
555d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
556d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
557d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              strerror(-err), err);
558762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
559d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
560d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
56155bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    int transform_hint;
56255bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
56355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    if (err != 0) {
56455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
56555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall              strerror(-err), err);
566762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
56755bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    }
56855bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall
569d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): Figure out what the min/max values should be.
570b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->minImageCount = 2;
571b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->maxImageCount = 3;
572d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
573fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    capabilities->currentExtent =
574fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall        VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
575fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall
576d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): Figure out what the max extent should be. Maximum
577d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // texture dimension maybe?
578b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->minImageExtent = VkExtent2D{1, 1};
579b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->maxImageExtent = VkExtent2D{4096, 4096};
580d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
581fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    capabilities->maxImageArrayLayers = 1;
582fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall
58355bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    capabilities->supportedTransforms = kSupportedTransforms;
58455bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall    capabilities->currentTransform =
58555bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall        TranslateNativeToVulkanTransform(transform_hint);
586d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
587fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    // On Android, window composition is a WindowManager property, not something
588fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    // associated with the bufferqueue. It can't be changed from here.
589fe2662d9e32d994346e7705c54043d8eb90a3734Jesse Hall    capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
590d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
591d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): I think these are right, but haven't thought hard about
592d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // it. Do we need to query the driver for support of any of these?
593d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // Currently not included:
594d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not
595d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not
596b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall    capabilities->supportedUsageFlags =
5973fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
5983fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
5993fbc856120217247c72fb5ed88500000f3881c45Jesse Hall        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
600d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
601d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
602b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
603b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
604b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
605e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
606e278daf850a664a1f15c760c64a74d3649b6f812Courtney GoeltzenleuchterVkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev,
607e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter                                            VkSurfaceKHR surface_handle,
608622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            uint32_t* count,
609622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                            VkSurfaceFormatKHR* formats) {
610e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    const InstanceData& instance_data = GetData(pdev);
611e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter
6121356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // TODO(jessehall): Fill out the set of supported formats. Longer term, add
6131356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // a new gralloc method to query whether a (format, usage) pair is
6141356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // supported, and check that for each gralloc format that corresponds to a
6151356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // Vulkan format. Shorter term, just add a few more formats to the ones
6161356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    // hardcoded below.
617d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
618d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const VkSurfaceFormatKHR kFormats[] = {
6192676338dd692b7d1e1c276d82e6b0492db53ab2eJesse Hall        {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
6202676338dd692b7d1e1c276d82e6b0492db53ab2eJesse Hall        {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
6212676338dd692b7d1e1c276d82e6b0492db53ab2eJesse Hall        {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
622d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
623d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
624e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    uint32_t total_num_formats = kNumFormats;
625e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter
626e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    bool wide_color_support = false;
627e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    Surface& surface = *SurfaceFromHandle(surface_handle);
628e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    int err = native_window_get_wide_color_support(surface.window.get(),
629e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter                                                   &wide_color_support);
630e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    if (err) {
631e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        // Not allowed to return a more sensible error code, so do this
632e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        return VK_ERROR_OUT_OF_HOST_MEMORY;
633e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    }
634e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    ALOGV("wide_color_support is: %d", wide_color_support);
635e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    wide_color_support =
636e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        wide_color_support &&
637e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
638e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter
639e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    const VkSurfaceFormatKHR kWideColorFormats[] = {
640bca34c90fdef4e8132ca34a3f9493ab93c603ae7Courtney Goeltzenleuchter        {VK_FORMAT_R16G16B16A16_SFLOAT,
641bca34c90fdef4e8132ca34a3f9493ab93c603ae7Courtney Goeltzenleuchter         VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT},
642e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        {VK_FORMAT_A2R10G10B10_UNORM_PACK32,
643e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter         VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
644e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    };
645e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    const uint32_t kNumWideColorFormats =
646e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        sizeof(kWideColorFormats) / sizeof(kWideColorFormats[0]);
647e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    if (wide_color_support) {
648e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        total_num_formats += kNumWideColorFormats;
649e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter    }
650d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
651d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
652d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (formats) {
653e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        uint32_t out_count = 0;
654e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        uint32_t transfer_count = 0;
655e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        if (*count < total_num_formats)
656d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            result = VK_INCOMPLETE;
657e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        transfer_count = std::min(*count, kNumFormats);
658e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        std::copy(kFormats, kFormats + transfer_count, formats);
659e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        out_count += transfer_count;
660e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        if (wide_color_support) {
661e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter            transfer_count = std::min(*count - out_count, kNumWideColorFormats);
662e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter            std::copy(kWideColorFormats, kWideColorFormats + transfer_count,
663e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter                      formats + out_count);
664e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter            out_count += transfer_count;
665e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        }
666e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        *count = out_count;
6677331e228f5089a619a517630351353e88d04c9b5Jesse Hall    } else {
668e278daf850a664a1f15c760c64a74d3649b6f812Courtney Goeltzenleuchter        *count = total_num_formats;
669d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
670d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return result;
671b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
672b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
673e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
6742452cf7e653c425191791a4fb546106d6a277654Chris ForbesVkResult GetPhysicalDeviceSurfaceCapabilities2KHR(
6752452cf7e653c425191791a4fb546106d6a277654Chris Forbes    VkPhysicalDevice physicalDevice,
6762452cf7e653c425191791a4fb546106d6a277654Chris Forbes    const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
6772452cf7e653c425191791a4fb546106d6a277654Chris Forbes    VkSurfaceCapabilities2KHR* pSurfaceCapabilities) {
6782452cf7e653c425191791a4fb546106d6a277654Chris Forbes    VkResult result = GetPhysicalDeviceSurfaceCapabilitiesKHR(
6792452cf7e653c425191791a4fb546106d6a277654Chris Forbes        physicalDevice, pSurfaceInfo->surface,
6802452cf7e653c425191791a4fb546106d6a277654Chris Forbes        &pSurfaceCapabilities->surfaceCapabilities);
6812452cf7e653c425191791a4fb546106d6a277654Chris Forbes
68206bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes    VkSurfaceCapabilities2KHR* caps = pSurfaceCapabilities;
68306bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes    while (caps->pNext) {
68406bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes        caps = reinterpret_cast<VkSurfaceCapabilities2KHR*>(caps->pNext);
68506bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes
68606bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes        switch (caps->sType) {
68706bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes            case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: {
68806bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                VkSharedPresentSurfaceCapabilitiesKHR* shared_caps =
68906bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                    reinterpret_cast<VkSharedPresentSurfaceCapabilitiesKHR*>(
69006bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                        caps);
69106bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                // Claim same set of usage flags are supported for
69206bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                // shared present modes as for other modes.
69306bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                shared_caps->sharedPresentSupportedUsageFlags =
69406bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                    pSurfaceCapabilities->surfaceCapabilities
69506bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                        .supportedUsageFlags;
69606bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes            } break;
69706bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes
69806bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes            default:
69906bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                // Ignore all other extension structs
70006bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes                break;
70106bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes        }
70206bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes    }
70306bc009ca14efd3869f2acf0de6ace9f9beb3c0bChris Forbes
7042452cf7e653c425191791a4fb546106d6a277654Chris Forbes    return result;
7052452cf7e653c425191791a4fb546106d6a277654Chris Forbes}
7062452cf7e653c425191791a4fb546106d6a277654Chris Forbes
7072452cf7e653c425191791a4fb546106d6a277654Chris ForbesVKAPI_ATTR
7082452cf7e653c425191791a4fb546106d6a277654Chris ForbesVkResult GetPhysicalDeviceSurfaceFormats2KHR(
7092452cf7e653c425191791a4fb546106d6a277654Chris Forbes    VkPhysicalDevice physicalDevice,
7102452cf7e653c425191791a4fb546106d6a277654Chris Forbes    const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
7112452cf7e653c425191791a4fb546106d6a277654Chris Forbes    uint32_t* pSurfaceFormatCount,
7122452cf7e653c425191791a4fb546106d6a277654Chris Forbes    VkSurfaceFormat2KHR* pSurfaceFormats) {
7132452cf7e653c425191791a4fb546106d6a277654Chris Forbes    if (!pSurfaceFormats) {
7142452cf7e653c425191791a4fb546106d6a277654Chris Forbes        return GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice,
7152452cf7e653c425191791a4fb546106d6a277654Chris Forbes                                                  pSurfaceInfo->surface,
7162452cf7e653c425191791a4fb546106d6a277654Chris Forbes                                                  pSurfaceFormatCount, nullptr);
7172452cf7e653c425191791a4fb546106d6a277654Chris Forbes    } else {
7182452cf7e653c425191791a4fb546106d6a277654Chris Forbes        // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
7192452cf7e653c425191791a4fb546106d6a277654Chris Forbes        // after the call.
7202452cf7e653c425191791a4fb546106d6a277654Chris Forbes        android::Vector<VkSurfaceFormatKHR> surface_formats;
7212452cf7e653c425191791a4fb546106d6a277654Chris Forbes        surface_formats.resize(*pSurfaceFormatCount);
7222452cf7e653c425191791a4fb546106d6a277654Chris Forbes        VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
7232452cf7e653c425191791a4fb546106d6a277654Chris Forbes            physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
7242452cf7e653c425191791a4fb546106d6a277654Chris Forbes            &surface_formats.editItemAt(0));
7252452cf7e653c425191791a4fb546106d6a277654Chris Forbes
7262452cf7e653c425191791a4fb546106d6a277654Chris Forbes        if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
7272452cf7e653c425191791a4fb546106d6a277654Chris Forbes            // marshal results individually due to stride difference.
7282452cf7e653c425191791a4fb546106d6a277654Chris Forbes            // completely ignore any chained extension structs.
7292452cf7e653c425191791a4fb546106d6a277654Chris Forbes            uint32_t formats_to_marshal = *pSurfaceFormatCount;
7302452cf7e653c425191791a4fb546106d6a277654Chris Forbes            for (uint32_t i = 0u; i < formats_to_marshal; i++) {
7312452cf7e653c425191791a4fb546106d6a277654Chris Forbes                pSurfaceFormats[i].surfaceFormat = surface_formats[i];
7322452cf7e653c425191791a4fb546106d6a277654Chris Forbes            }
7332452cf7e653c425191791a4fb546106d6a277654Chris Forbes        }
7342452cf7e653c425191791a4fb546106d6a277654Chris Forbes
7352452cf7e653c425191791a4fb546106d6a277654Chris Forbes        return result;
7362452cf7e653c425191791a4fb546106d6a277654Chris Forbes    }
7372452cf7e653c425191791a4fb546106d6a277654Chris Forbes}
7382452cf7e653c425191791a4fb546106d6a277654Chris Forbes
7392452cf7e653c425191791a4fb546106d6a277654Chris ForbesVKAPI_ATTR
740e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris ForbesVkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev,
741622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                                 VkSurfaceKHR /*surface*/,
742622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                                 uint32_t* count,
743622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                                 VkPresentModeKHR* modes) {
744e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes    android::Vector<VkPresentModeKHR> present_modes;
745e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes    present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
746e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes    present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
747e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes
748e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes    VkPhysicalDevicePresentationPropertiesANDROID present_properties;
749e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes    if (QueryPresentationProperties(pdev, &present_properties)) {
750e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes        if (present_properties.sharedImage) {
751e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes            present_modes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR);
752e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes            present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
753e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes        }
754e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes    }
755e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes
756e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes    uint32_t num_modes = uint32_t(present_modes.size());
757d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
758d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
759d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (modes) {
760e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes        if (*count < num_modes)
761d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            result = VK_INCOMPLETE;
762e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes        *count = std::min(*count, num_modes);
763e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes        std::copy(present_modes.begin(), present_modes.begin() + int(*count), modes);
7647331e228f5089a619a517630351353e88d04c9b5Jesse Hall    } else {
765e8d79a60cf5edc9ce0b025e39e3731fabcd2fdf4Chris Forbes        *count = num_modes;
766d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
767d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return result;
768b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
769b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
770e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
771622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult CreateSwapchainKHR(VkDevice device,
772622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                            const VkSwapchainCreateInfoKHR* create_info,
773622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                            const VkAllocationCallbacks* allocator,
774622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                            VkSwapchainKHR* swapchain_handle) {
775d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int err;
776d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
777d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
7783d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
7793d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          " minImageCount=%u imageFormat=%u imageColorSpace=%u"
7803d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
7813d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          " oldSwapchain=0x%" PRIx64,
7823d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          reinterpret_cast<uint64_t>(create_info->surface),
7833d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          create_info->minImageCount, create_info->imageFormat,
7843d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          create_info->imageColorSpace, create_info->imageExtent.width,
7853d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          create_info->imageExtent.height, create_info->imageUsage,
7863d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          create_info->preTransform, create_info->presentMode,
7873d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall          reinterpret_cast<uint64_t>(create_info->oldSwapchain));
7883d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
7891f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    if (!allocator)
7904a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu        allocator = &GetData(device).allocator;
7911f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall
7927d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    android_pixel_format native_pixel_format =
7937d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        GetNativePixelFormat(create_info->imageFormat);
7947d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    android_dataspace native_dataspace =
7957d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        GetNativeDataspace(create_info->imageColorSpace);
7967d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    if (native_dataspace == HAL_DATASPACE_UNKNOWN) {
7977d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        ALOGE(
7987d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            "CreateSwapchainKHR(VkSwapchainCreateInfoKHR.imageColorSpace = %d) "
7997d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            "failed: Unsupported color space",
8007d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter            create_info->imageColorSpace);
8017d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter        return VK_ERROR_INITIALIZATION_FAILED;
8027d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    }
8037d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter
80442a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ALOGV_IF(create_info->imageArrayLayers != 1,
805dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "swapchain imageArrayLayers=%u not supported",
806715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall             create_info->imageArrayLayers);
80742a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ALOGV_IF((create_info->preTransform & ~kSupportedTransforms) != 0,
808dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "swapchain preTransform=%#x not supported",
80955bc09788673f8f35bfb2450028827d5ea76c1d3Jesse Hall             create_info->preTransform);
81042a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ALOGV_IF(!(create_info->presentMode == VK_PRESENT_MODE_FIFO_KHR ||
811980ad05eb054386f62395bdf16298581d2a5b09eChris Forbes               create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ||
8121d5f68c10560a82fd3278e17e934ee3bff328374Chris Forbes               create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
8131d5f68c10560a82fd3278e17e934ee3bff328374Chris Forbes               create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR),
814dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "swapchain presentMode=%u not supported",
8150ae0dceca1fb83e095d8de6b811aa193def238a0Jesse Hall             create_info->presentMode);
816d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
8173d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    Surface& surface = *SurfaceFromHandle(create_info->surface);
8183d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
819dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (surface.swapchain_handle != create_info->oldSwapchain) {
82042a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall        ALOGV("Can't create a swapchain for VkSurfaceKHR 0x%" PRIx64
821dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              " because it already has active swapchain 0x%" PRIx64
822dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              " but VkSwapchainCreateInfo::oldSwapchain=0x%" PRIx64,
823dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              reinterpret_cast<uint64_t>(create_info->surface),
824dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              reinterpret_cast<uint64_t>(surface.swapchain_handle),
825dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall              reinterpret_cast<uint64_t>(create_info->oldSwapchain));
826dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
827dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
828dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (create_info->oldSwapchain != VK_NULL_HANDLE)
829dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        OrphanSwapchain(device, SwapchainFromHandle(create_info->oldSwapchain));
830dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
8313d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // -- Reset the native window --
8323d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // The native window might have been used previously, and had its properties
8333d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // changed from defaults. That will affect the answer we get for queries
8343d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we
8353d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    // attempt such queries.
8363d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
837dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // The native window only allows dequeueing all buffers before any have
838dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // been queued, since after that point at least one is assumed to be in
839dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // non-FREE state at any given time. Disconnecting and re-connecting
840dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // orphans the previous buffers, getting us back to the state where we can
841dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // dequeue all buffers.
842dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    err = native_window_api_disconnect(surface.window.get(),
843dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                                       NATIVE_WINDOW_API_EGL);
844dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)",
845dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             strerror(-err), err);
846dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    err =
847dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        native_window_api_connect(surface.window.get(), NATIVE_WINDOW_API_EGL);
848dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOGW_IF(err != 0, "native_window_api_connect failed: %s (%d)",
849dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             strerror(-err), err);
850dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
8513d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    err = native_window_set_buffer_count(surface.window.get(), 0);
8523d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    if (err != 0) {
8533d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
8543d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall              strerror(-err), err);
855762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
8563d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    }
8573d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
8589b7e453d71e9c17477c097f5f28f1b9d3a134998Hrishikesh Manohar    int swap_interval =
8599b7e453d71e9c17477c097f5f28f1b9d3a134998Hrishikesh Manohar        create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
8609b7e453d71e9c17477c097f5f28f1b9d3a134998Hrishikesh Manohar    err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
8613d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    if (err != 0) {
8623d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
8633d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        // errors and translate them to valid Vulkan result codes?
8643d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
8653d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall              strerror(-err), err);
866762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
8673d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall    }
8683d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall
869b8042d26de26e9212e62518b39147008937c7729Chris Forbes    err = native_window_set_shared_buffer_mode(surface.window.get(), false);
870b8042d26de26e9212e62518b39147008937c7729Chris Forbes    if (err != 0) {
871b8042d26de26e9212e62518b39147008937c7729Chris Forbes        ALOGE("native_window_set_shared_buffer_mode(false) failed: %s (%d)",
872b8042d26de26e9212e62518b39147008937c7729Chris Forbes              strerror(-err), err);
873762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
874b8042d26de26e9212e62518b39147008937c7729Chris Forbes    }
875b8042d26de26e9212e62518b39147008937c7729Chris Forbes
876b8042d26de26e9212e62518b39147008937c7729Chris Forbes    err = native_window_set_auto_refresh(surface.window.get(), false);
877b8042d26de26e9212e62518b39147008937c7729Chris Forbes    if (err != 0) {
878b8042d26de26e9212e62518b39147008937c7729Chris Forbes        ALOGE("native_window_set_auto_refresh(false) failed: %s (%d)",
879b8042d26de26e9212e62518b39147008937c7729Chris Forbes              strerror(-err), err);
880762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
881b8042d26de26e9212e62518b39147008937c7729Chris Forbes    }
882b8042d26de26e9212e62518b39147008937c7729Chris Forbes
883d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Configure the native window --
884d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
8854a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu    const auto& dispatch = GetData(device).driver;
88670f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall
8877d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter    err = native_window_set_buffers_format(surface.window.get(),
8887d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter                                           native_pixel_format);
889517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    if (err != 0) {
890517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
891517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        // errors and translate them to valid Vulkan result codes?
892517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
8937d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter              native_pixel_format, strerror(-err), err);
894762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
895517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    }
896517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    err = native_window_set_buffers_data_space(surface.window.get(),
8977d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter                                               native_dataspace);
898517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    if (err != 0) {
899517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
900517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        // errors and translate them to valid Vulkan result codes?
901517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
9027d4a64a6ada75c773e9fc39f27a9220be32d084bCourtney Goeltzenleuchter              native_dataspace, strerror(-err), err);
903762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
904517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall    }
905517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall
9063dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall    err = native_window_set_buffers_dimensions(
9073dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall        surface.window.get(), static_cast<int>(create_info->imageExtent.width),
9083dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall        static_cast<int>(create_info->imageExtent.height));
909d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
910d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
911d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
912d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
913d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              create_info->imageExtent.width, create_info->imageExtent.height,
914d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall              strerror(-err), err);
915762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
916d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
917d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
918178b69664a5f56470c143b5930162f285adc83faJesse Hall    // VkSwapchainCreateInfo::preTransform indicates the transformation the app
919178b69664a5f56470c143b5930162f285adc83faJesse Hall    // applied during rendering. native_window_set_transform() expects the
920178b69664a5f56470c143b5930162f285adc83faJesse Hall    // inverse: the transform the app is requesting that the compositor perform
921178b69664a5f56470c143b5930162f285adc83faJesse Hall    // during composition. With native windows, pre-transform works by rendering
922178b69664a5f56470c143b5930162f285adc83faJesse Hall    // with the same transform the compositor is applying (as in Vulkan), but
923178b69664a5f56470c143b5930162f285adc83faJesse Hall    // then requesting the inverse transform, so that when the compositor does
924178b69664a5f56470c143b5930162f285adc83faJesse Hall    // it's job the two transforms cancel each other out and the compositor ends
925178b69664a5f56470c143b5930162f285adc83faJesse Hall    // up applying an identity transform to the app's buffer.
926178b69664a5f56470c143b5930162f285adc83faJesse Hall    err = native_window_set_buffers_transform(
927178b69664a5f56470c143b5930162f285adc83faJesse Hall        surface.window.get(),
928178b69664a5f56470c143b5930162f285adc83faJesse Hall        InvertTransformToNative(create_info->preTransform));
929178b69664a5f56470c143b5930162f285adc83faJesse Hall    if (err != 0) {
930178b69664a5f56470c143b5930162f285adc83faJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
931178b69664a5f56470c143b5930162f285adc83faJesse Hall        // errors and translate them to valid Vulkan result codes?
932178b69664a5f56470c143b5930162f285adc83faJesse Hall        ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
933178b69664a5f56470c143b5930162f285adc83faJesse Hall              InvertTransformToNative(create_info->preTransform),
934178b69664a5f56470c143b5930162f285adc83faJesse Hall              strerror(-err), err);
935762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
936178b69664a5f56470c143b5930162f285adc83faJesse Hall    }
937178b69664a5f56470c143b5930162f285adc83faJesse Hall
938f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall    err = native_window_set_scaling_mode(
9391356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
940f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall    if (err != 0) {
941f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
942f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        // errors and translate them to valid Vulkan result codes?
943f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall        ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
944f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall              strerror(-err), err);
945762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
946f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall    }
947f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall
94897ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes    VkSwapchainImageUsageFlagsANDROID swapchain_image_usage = 0;
94997ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes    if (create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
95097ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes        create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
95197ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes        swapchain_image_usage |= VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID;
95297ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes        err = native_window_set_shared_buffer_mode(surface.window.get(), true);
95397ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes        if (err != 0) {
95497ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes            ALOGE("native_window_set_shared_buffer_mode failed: %s (%d)", strerror(-err), err);
95597ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes            return VK_ERROR_SURFACE_LOST_KHR;
95697ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes        }
95797ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes    }
95897ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes
95997ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes    if (create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
96097ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes        err = native_window_set_auto_refresh(surface.window.get(), true);
96197ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes        if (err != 0) {
96297ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes            ALOGE("native_window_set_auto_refresh failed: %s (%d)", strerror(-err), err);
96397ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes            return VK_ERROR_SURFACE_LOST_KHR;
96497ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes        }
96597ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes    }
96697ef461b1b6277f0f31f00e9c390424eb71392dfChris Forbes
967e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall    int query_value;
968e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall    err = surface.window->query(surface.window.get(),
969e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall                                NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
970e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall                                &query_value);
971e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall    if (err != 0 || query_value < 0) {
972d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
973d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
974e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
975e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall              query_value);
976762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
977d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
978e6080bf2e54aa0d548b0eb571ad2eef2c52e5fb6Jesse Hall    uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
979d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t num_images =
980d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        (create_info->minImageCount - 1) + min_undequeued_buffers;
9812c8fc75cca5e42b4f07b589cef6e78f3dff49ae0Chris Forbes
9822c8fc75cca5e42b4f07b589cef6e78f3dff49ae0Chris Forbes    // Lower layer insists that we have at least two buffers. This is wasteful
9832c8fc75cca5e42b4f07b589cef6e78f3dff49ae0Chris Forbes    // and we'd like to relax it in the shared case, but not all the pieces are
9842c8fc75cca5e42b4f07b589cef6e78f3dff49ae0Chris Forbes    // in place for that to work yet. Note we only lie to the lower layer-- we
9852c8fc75cca5e42b4f07b589cef6e78f3dff49ae0Chris Forbes    // don't want to give the app back a swapchain with extra images (which they
9862c8fc75cca5e42b4f07b589cef6e78f3dff49ae0Chris Forbes    // can't actually use!).
9872c8fc75cca5e42b4f07b589cef6e78f3dff49ae0Chris Forbes    err = native_window_set_buffer_count(surface.window.get(), std::max(2u, num_images));
988d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
989d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
990d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
9913d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall        ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
9923d1c82a750046f055951242bf27909ad7d9cdf52Jesse Hall              strerror(-err), err);
993762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
994d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
995d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
99670f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    int gralloc_usage = 0;
9978c47dc9136aa26ee749bbe952db04f6b2fc79399Chris Forbes    if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
998d1abd7456e10f46200a90e8a0e5a1a8bef0a388aJesse Hall        uint64_t consumer_usage, producer_usage;
999894780b0ac8f3cdb90e52c45f4fe34494131f70bCourtney Goeltzenleuchter        result = dispatch.GetSwapchainGrallocUsage2ANDROID(
1000894780b0ac8f3cdb90e52c45f4fe34494131f70bCourtney Goeltzenleuchter            device, create_info->imageFormat, create_info->imageUsage,
1001894780b0ac8f3cdb90e52c45f4fe34494131f70bCourtney Goeltzenleuchter            swapchain_image_usage, &consumer_usage, &producer_usage);
10028c47dc9136aa26ee749bbe952db04f6b2fc79399Chris Forbes        if (result != VK_SUCCESS) {
10038c47dc9136aa26ee749bbe952db04f6b2fc79399Chris Forbes            ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
1004762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan            return VK_ERROR_SURFACE_LOST_KHR;
10058c47dc9136aa26ee749bbe952db04f6b2fc79399Chris Forbes        }
1006d1abd7456e10f46200a90e8a0e5a1a8bef0a388aJesse Hall        gralloc_usage =
10077992781a574b1c52a203e9271772da16f0f06812Jesse Hall            android_convertGralloc1To0Usage(producer_usage, consumer_usage);
10088c47dc9136aa26ee749bbe952db04f6b2fc79399Chris Forbes    } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
10091f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall        result = dispatch.GetSwapchainGrallocUsageANDROID(
1010f4ab2b18391ab5045b44af9ea1d5698af7c2a0cdJesse Hall            device, create_info->imageFormat, create_info->imageUsage,
101170f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall            &gralloc_usage);
101270f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        if (result != VK_SUCCESS) {
101370f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall            ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
1014762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan            return VK_ERROR_SURFACE_LOST_KHR;
101570f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        }
101670f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    }
10171356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    err = native_window_set_usage(surface.window.get(), gralloc_usage);
101870f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    if (err != 0) {
101970f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
102070f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        // errors and translate them to valid Vulkan result codes?
102170f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
1022762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
102370f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall    }
1024d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1025d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Allocate our Swapchain object --
1026d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // After this point, we must deallocate the swapchain on error.
1027d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
10281f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    void* mem = allocator->pfnAllocation(allocator->pUserData,
10291f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                                         sizeof(Swapchain), alignof(Swapchain),
10301f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
10311356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    if (!mem)
1032d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return VK_ERROR_OUT_OF_HOST_MEMORY;
1033ffedb65cea7551bc689552c0bc21343f568d000eIan Elliott    Swapchain* swapchain =
1034ffedb65cea7551bc689552c0bc21343f568d000eIan Elliott        new (mem) Swapchain(surface, num_images, create_info->presentMode);
1035d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1036d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Dequeue all buffers and create a VkImage for each --
1037d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // Any failures during or after this must cancel the dequeued buffers.
1038d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1039b56287ad73b9ea1c8e9d0a24dc3605e8aae06903Chris Forbes    VkSwapchainImageCreateInfoANDROID swapchain_image_create = {
1040b56287ad73b9ea1c8e9d0a24dc3605e8aae06903Chris Forbes#pragma clang diagnostic push
1041b56287ad73b9ea1c8e9d0a24dc3605e8aae06903Chris Forbes#pragma clang diagnostic ignored "-Wold-style-cast"
1042b56287ad73b9ea1c8e9d0a24dc3605e8aae06903Chris Forbes        .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID,
1043b56287ad73b9ea1c8e9d0a24dc3605e8aae06903Chris Forbes#pragma clang diagnostic pop
1044b56287ad73b9ea1c8e9d0a24dc3605e8aae06903Chris Forbes        .pNext = nullptr,
1045b56287ad73b9ea1c8e9d0a24dc3605e8aae06903Chris Forbes        .usage = swapchain_image_usage,
1046b56287ad73b9ea1c8e9d0a24dc3605e8aae06903Chris Forbes    };
1047d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkNativeBufferANDROID image_native_buffer = {
1048d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic push
1049d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wold-style-cast"
1050d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
1051d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic pop
1052b56287ad73b9ea1c8e9d0a24dc3605e8aae06903Chris Forbes        .pNext = &swapchain_image_create,
1053d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
1054d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkImageCreateInfo image_create = {
1055d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1056d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .pNext = &image_native_buffer,
1057d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .imageType = VK_IMAGE_TYPE_2D,
1058517274a29e50522a11e65107bb2c0d5b123aa7d5Jesse Hall        .format = create_info->imageFormat,
1059d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .extent = {0, 0, 1},
1060d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .mipLevels = 1,
1061a15a4bf4bafd6114ae8f28c2df2fc622cb3baaceJesse Hall        .arrayLayers = 1,
1062091ed9e69400edcc549c9b11635d1a305d6b5a83Jesse Hall        .samples = VK_SAMPLE_COUNT_1_BIT,
1063d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .tiling = VK_IMAGE_TILING_OPTIMAL,
1064f4ab2b18391ab5045b44af9ea1d5698af7c2a0cdJesse Hall        .usage = create_info->imageUsage,
1065d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .flags = 0,
1066f4ab2b18391ab5045b44af9ea1d5698af7c2a0cdJesse Hall        .sharingMode = create_info->imageSharingMode,
106703b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall        .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
1068d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
1069d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    };
1070d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1071d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (uint32_t i = 0; i < num_images; i++) {
1072d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Swapchain::Image& img = swapchain->images[i];
1073d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1074d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ANativeWindowBuffer* buffer;
10751356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall        err = surface.window->dequeueBuffer(surface.window.get(), &buffer,
10761356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall                                            &img.dequeue_fence);
1077d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (err != 0) {
1078d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // TODO(jessehall): Improve error reporting. Can we enumerate
1079d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            // possible errors and translate them to valid Vulkan result codes?
1080d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
1081762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan            result = VK_ERROR_SURFACE_LOST_KHR;
1082d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            break;
1083d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
1084e8e689f1190a936ebd6bf6cbe28ab8625e94c6c7Chia-I Wu        img.buffer = buffer;
1085d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        img.dequeued = true;
1086d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1087d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_create.extent =
10883dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall            VkExtent3D{static_cast<uint32_t>(img.buffer->width),
10893dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall                       static_cast<uint32_t>(img.buffer->height),
10903dd678a6a30e2d94bfd570ec43ffd379e9c5d409Jesse Hall                       1};
1091d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.handle = img.buffer->handle;
1092d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.stride = img.buffer->stride;
1093d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.format = img.buffer->format;
1094d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        image_native_buffer.usage = img.buffer->usage;
10954744291270cc6c8d0838fab2bc1e954524dbfcbcChris Forbes        android_convertGralloc0To1Usage(img.buffer->usage,
10964744291270cc6c8d0838fab2bc1e954524dbfcbcChris Forbes            &image_native_buffer.usage2.producer,
10974744291270cc6c8d0838fab2bc1e954524dbfcbcChris Forbes            &image_native_buffer.usage2.consumer);
1098d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
109903b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall        result =
11001f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall            dispatch.CreateImage(device, &image_create, nullptr, &img.image);
1101d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (result != VK_SUCCESS) {
1102d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGD("vkCreateImage w/ native buffer failed: %u", result);
1103d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            break;
1104d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
1105d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1106d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1107d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // -- Cancel all buffers, returning them to the queue --
1108d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // If an error occurred before, also destroy the VkImage and release the
1109d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // buffer reference. Otherwise, we retain a strong reference to the buffer.
1110d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    //
1111d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // TODO(jessehall): The error path here is the same as DestroySwapchain,
1112d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    // but not the non-error path. Should refactor/unify.
1113e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes    if (!swapchain->shared) {
1114e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes        for (uint32_t i = 0; i < num_images; i++) {
1115e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes            Swapchain::Image& img = swapchain->images[i];
1116e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes            if (img.dequeued) {
1117e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes                surface.window->cancelBuffer(surface.window.get(), img.buffer.get(),
1118e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes                                             img.dequeue_fence);
1119e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes                img.dequeue_fence = -1;
1120e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes                img.dequeued = false;
1121e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes            }
1122e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes            if (result != VK_SUCCESS) {
1123e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes                if (img.image)
1124e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes                    dispatch.DestroyImage(device, img.image, nullptr);
1125e0ced03e62565f42b3005ec34481ef2be7ae2d4bChris Forbes            }
1126d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
1127d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1128d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1129d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (result != VK_SUCCESS) {
1130d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        swapchain->~Swapchain();
11311f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall        allocator->pfnFree(allocator->pUserData, swapchain);
1132d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return result;
1133d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1134d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1135dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    surface.swapchain_handle = HandleFromSwapchain(swapchain);
1136dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    *swapchain_handle = surface.swapchain_handle;
1137b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
1138b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
1139b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
1140e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
1141622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wuvoid DestroySwapchainKHR(VkDevice device,
1142622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                         VkSwapchainKHR swapchain_handle,
1143622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                         const VkAllocationCallbacks* allocator) {
11444a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu    const auto& dispatch = GetData(device).driver;
1145d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
1146d78c2e8a0807ff45db4cb643cc2ef38eafd22551Daniel Koch    if (!swapchain)
1147d78c2e8a0807ff45db4cb643cc2ef38eafd22551Daniel Koch        return;
114842a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    bool active = swapchain->surface.swapchain_handle == swapchain_handle;
114942a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
1150dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
11514c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    if (swapchain->frame_timestamps_enabled) {
11524c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott        native_window_enable_frame_timestamps(window, false);
11534c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    }
1154dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    for (uint32_t i = 0; i < swapchain->num_images; i++)
1155dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
115642a9eecb23c0b72bbee1eb2ef6b0d6586159d1c3Jesse Hall    if (active)
1157dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
11581f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    if (!allocator)
11594a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu        allocator = &GetData(device).allocator;
1160d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    swapchain->~Swapchain();
11611f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall    allocator->pfnFree(allocator->pUserData, swapchain);
1162b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
1163b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
1164e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
1165622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult GetSwapchainImagesKHR(VkDevice,
1166622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                               VkSwapchainKHR swapchain_handle,
1167622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                               uint32_t* count,
1168622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                               VkImage* images) {
1169d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
1170dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOGW_IF(swapchain.surface.swapchain_handle != swapchain_handle,
1171dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "getting images for non-active swapchain 0x%" PRIx64
1172dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             "; only dequeued image handles are valid",
1173dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall             reinterpret_cast<uint64_t>(swapchain_handle));
1174d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result = VK_SUCCESS;
1175d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (images) {
1176d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        uint32_t n = swapchain.num_images;
1177d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (*count < swapchain.num_images) {
1178d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            n = *count;
1179d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            result = VK_INCOMPLETE;
1180d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
1181d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        for (uint32_t i = 0; i < n; i++)
1182d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            images[i] = swapchain.images[i].image;
11837331e228f5089a619a517630351353e88d04c9b5Jesse Hall        *count = n;
11847331e228f5089a619a517630351353e88d04c9b5Jesse Hall    } else {
11857331e228f5089a619a517630351353e88d04c9b5Jesse Hall        *count = swapchain.num_images;
1186d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1187d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return result;
1188b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
1189b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
1190e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
1191622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult AcquireNextImageKHR(VkDevice device,
1192622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             VkSwapchainKHR swapchain_handle,
1193622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             uint64_t timeout,
1194622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             VkSemaphore semaphore,
1195622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             VkFence vk_fence,
1196622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                             uint32_t* image_index) {
1197d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
11981356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall    ANativeWindow* window = swapchain.surface.window.get();
1199d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult result;
1200d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int err;
1201d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1202dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    if (swapchain.surface.swapchain_handle != swapchain_handle)
1203dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        return VK_ERROR_OUT_OF_DATE_KHR;
1204dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
1205d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGW_IF(
1206d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        timeout != UINT64_MAX,
1207d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented");
1208d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1209c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes    if (swapchain.shared) {
1210c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes        // In shared mode, we keep the buffer dequeued all the time, so we don't
1211c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes        // want to dequeue a buffer here. Instead, just ask the driver to ensure
1212c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes        // the semaphore and fence passed to us will be signalled.
1213c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes        *image_index = 0;
1214c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes        result = GetData(device).driver.AcquireImageANDROID(
1215c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes                device, swapchain.images[*image_index].image, -1, semaphore, vk_fence);
1216c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes        return result;
1217c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes    }
1218c88409c2b8e99be8d5f134e260c4c29b1e632b3cChris Forbes
1219d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ANativeWindowBuffer* buffer;
1220061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall    int fence_fd;
1221061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall    err = window->dequeueBuffer(window, &buffer, &fence_fd);
1222d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (err != 0) {
1223d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // TODO(jessehall): Improve error reporting. Can we enumerate possible
1224d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        // errors and translate them to valid Vulkan result codes?
1225d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
1226762c813cd0fdcf41760a7be9b8c73bfa246289c2Mike Stroyan        return VK_ERROR_SURFACE_LOST_KHR;
1227d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1228d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1229d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    uint32_t idx;
1230d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (idx = 0; idx < swapchain.num_images; idx++) {
1231d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (swapchain.images[idx].buffer.get() == buffer) {
1232d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            swapchain.images[idx].dequeued = true;
1233061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall            swapchain.images[idx].dequeue_fence = fence_fd;
1234d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            break;
1235d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
1236d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1237d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (idx == swapchain.num_images) {
1238d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        ALOGE("dequeueBuffer returned unrecognized buffer");
1239061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall        window->cancelBuffer(window, buffer, fence_fd);
1240d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return VK_ERROR_OUT_OF_DATE_KHR;
1241d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1242d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1243d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    int fence_clone = -1;
1244061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall    if (fence_fd != -1) {
1245061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall        fence_clone = dup(fence_fd);
1246d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (fence_clone == -1) {
1247d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall            ALOGE("dup(fence) failed, stalling until signalled: %s (%d)",
1248d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall                  strerror(errno), errno);
1249061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall            sync_wait(fence_fd, -1 /* forever */);
1250d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
1251d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1252d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
12534a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu    result = GetData(device).driver.AcquireImageANDROID(
12541f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall        device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence);
1255d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    if (result != VK_SUCCESS) {
1256ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // NOTE: we're relying on AcquireImageANDROID to close fence_clone,
1257ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // even if the call fails. We could close it ourselves on failure, but
1258ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // that would create a race condition if the driver closes it on a
1259ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // failure path: some other thread might create an fd with the same
1260ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // number between the time the driver closes it and the time we close
1261ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // it. We must assume one of: the driver *always* closes it even on
1262ab9aeef063119445b59166f781c464c64e3909dbJesse Hall        // failure, or *never* closes it on failure.
1263061938022b3f5f37f7aaebf7ccc8ac20bf4dbf97Jesse Hall        window->cancelBuffer(window, buffer, fence_fd);
1264d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        swapchain.images[idx].dequeued = false;
1265d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        swapchain.images[idx].dequeue_fence = -1;
1266d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        return result;
1267d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1268d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1269d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    *image_index = idx;
1270b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall    return VK_SUCCESS;
1271b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}
1272b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
1273dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hallstatic VkResult WorstPresentResult(VkResult a, VkResult b) {
1274dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // See the error ranking for vkQueuePresentKHR at the end of section 29.6
1275dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    // (in spec version 1.0.14).
1276dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    static const VkResult kWorstToBest[] = {
1277dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_DEVICE_LOST,
1278dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_SURFACE_LOST_KHR,
1279dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_OUT_OF_DATE_KHR,
1280dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_OUT_OF_DEVICE_MEMORY,
1281dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_ERROR_OUT_OF_HOST_MEMORY,
1282dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VK_SUBOPTIMAL_KHR,
1283dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    };
1284dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    for (auto result : kWorstToBest) {
1285dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (a == result || b == result)
1286dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            return result;
1287dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    }
1288dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOG_ASSERT(a == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", a);
1289dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    ALOG_ASSERT(b == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", b);
1290dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    return a != VK_SUCCESS ? a : b;
1291dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall}
1292dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
1293e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR
1294622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
1295d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1296d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
1297d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall             present_info->sType);
1298d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1299dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall    VkDevice device = GetData(queue).driver_device;
13004a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu    const auto& dispatch = GetData(queue).driver;
1301d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    VkResult final_result = VK_SUCCESS;
1302dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
1303cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    // Look at the pNext chain for supported extension structs:
13044c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    const VkPresentRegionsKHR* present_regions = nullptr;
13054c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    const VkPresentTimesInfoGOOGLE* present_times = nullptr;
1306cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    const VkPresentRegionsKHR* next =
1307cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott        reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext);
1308cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    while (next) {
1309cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott        switch (next->sType) {
1310cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott            case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
1311cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                present_regions = next;
1312cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                break;
131314866bbeca1ebcda93f43a3352934889a9f37c2bIan Elliott            case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE:
13144c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                present_times =
13154c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                    reinterpret_cast<const VkPresentTimesInfoGOOGLE*>(next);
13164c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                break;
1317cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott            default:
1318cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x",
1319cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                      next->sType);
1320cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                break;
1321cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott        }
1322cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott        next = reinterpret_cast<const VkPresentRegionsKHR*>(next->pNext);
1323cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    }
1324cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    ALOGV_IF(
1325cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott        present_regions &&
1326cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott            present_regions->swapchainCount != present_info->swapchainCount,
1327cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott        "VkPresentRegions::swapchainCount != VkPresentInfo::swapchainCount");
13284c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    ALOGV_IF(present_times &&
13294c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                 present_times->swapchainCount != present_info->swapchainCount,
13304c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott             "VkPresentTimesInfoGOOGLE::swapchainCount != "
13314c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott             "VkPresentInfo::swapchainCount");
1332cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    const VkPresentRegionKHR* regions =
13334c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott        (present_regions) ? present_regions->pRegions : nullptr;
13344c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    const VkPresentTimeGOOGLE* times =
13354c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott        (present_times) ? present_times->pTimes : nullptr;
1336cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    const VkAllocationCallbacks* allocator = &GetData(device).allocator;
13374c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    android_native_rect_t* rects = nullptr;
1338cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    uint32_t nrects = 0;
1339cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott
1340d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
1341d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        Swapchain& swapchain =
134203b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall            *SwapchainFromHandle(present_info->pSwapchains[sc]);
1343f4ab2b18391ab5045b44af9ea1d5698af7c2a0cdJesse Hall        uint32_t image_idx = present_info->pImageIndices[sc];
13445ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        Swapchain::Image& img = swapchain.images[image_idx];
1345ffedb65cea7551bc689552c0bc21343f568d000eIan Elliott        const VkPresentRegionKHR* region =
1346ffedb65cea7551bc689552c0bc21343f568d000eIan Elliott            (regions && !swapchain.mailbox_mode) ? &regions[sc] : nullptr;
13474c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott        const VkPresentTimeGOOGLE* time = (times) ? &times[sc] : nullptr;
1348dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        VkResult swapchain_result = VK_SUCCESS;
1349d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        VkResult result;
1350d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        int err;
1351d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1352d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        int fence = -1;
1353275d76c8158c90ec5317b82cb10b094bca2b43cfJesse Hall        result = dispatch.QueueSignalReleaseImageANDROID(
1354275d76c8158c90ec5317b82cb10b094bca2b43cfJesse Hall            queue, present_info->waitSemaphoreCount,
1355275d76c8158c90ec5317b82cb10b094bca2b43cfJesse Hall            present_info->pWaitSemaphores, img.image, &fence);
1356d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        if (result != VK_SUCCESS) {
1357ab9aeef063119445b59166f781c464c64e3909dbJesse Hall            ALOGE("QueueSignalReleaseImageANDROID failed: %d", result);
1358dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            swapchain_result = result;
1359d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
1360d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1361dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (swapchain.surface.swapchain_handle ==
1362dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            present_info->pSwapchains[sc]) {
1363dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            ANativeWindow* window = swapchain.surface.window.get();
1364dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            if (swapchain_result == VK_SUCCESS) {
1365cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                if (region) {
1366cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                    // Process the incremental-present hint for this swapchain:
1367cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                    uint32_t rcount = region->rectangleCount;
1368cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                    if (rcount > nrects) {
1369cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        android_native_rect_t* new_rects =
1370cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                            static_cast<android_native_rect_t*>(
1371cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                                allocator->pfnReallocation(
1372cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                                    allocator->pUserData, rects,
1373cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                                    sizeof(android_native_rect_t) * rcount,
1374cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                                    alignof(android_native_rect_t),
1375cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                                    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
1376cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        if (new_rects) {
1377cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                            rects = new_rects;
1378cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                            nrects = rcount;
1379cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        } else {
1380cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                            rcount = 0;  // Ignore the hint for this swapchain
1381cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        }
1382cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                    }
1383cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                    for (uint32_t r = 0; r < rcount; ++r) {
1384cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        if (region->pRectangles[r].layer > 0) {
1385cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                            ALOGV(
1386cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                                "vkQueuePresentKHR ignoring invalid layer "
1387cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                                "(%u); using layer 0 instead",
1388cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                                region->pRectangles[r].layer);
1389cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        }
1390cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        int x = region->pRectangles[r].offset.x;
1391cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        int y = region->pRectangles[r].offset.y;
1392cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        int width = static_cast<int>(
1393cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                            region->pRectangles[r].extent.width);
1394cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        int height = static_cast<int>(
1395cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                            region->pRectangles[r].extent.height);
1396cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        android_native_rect_t* cur_rect = &rects[r];
1397cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        cur_rect->left = x;
1398cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        cur_rect->top = y + height;
1399cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        cur_rect->right = x + width;
1400cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                        cur_rect->bottom = y;
1401cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                    }
1402cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                    native_window_set_surface_damage(window, rects, rcount);
1403cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott                }
14044c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                if (time) {
14054c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                    if (!swapchain.frame_timestamps_enabled) {
14068a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                        ALOGV(
14078a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                            "Calling "
14088a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                            "native_window_enable_frame_timestamps(true)");
14094c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                        native_window_enable_frame_timestamps(window, true);
14104c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                        swapchain.frame_timestamps_enabled = true;
14114c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                    }
14121049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
14131049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    // Record the nativeFrameId so it can be later correlated to
14141049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    // this present.
14151049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    uint64_t nativeFrameId = 0;
14161049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    err = native_window_get_next_frame_id(
14171049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                            window, &nativeFrameId);
14181049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    if (err != android::NO_ERROR) {
14191049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                        ALOGE("Failed to get next native frame ID.");
14201049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    }
14211049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson
14221049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    // Add a new timing record with the user's presentID and
14231049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    // the nativeFrameId.
14241049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    swapchain.timing.push_back(TimingInfo(time, nativeFrameId));
14251049d1d0b21ee318e309f9a90098c092cb879c41Brian Anderson                    while (swapchain.timing.size() > MAX_TIMING_INFOS) {
14268a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                        swapchain.timing.removeAt(0);
14278a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                    }
14288a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                    if (time->desiredPresentTime) {
14298a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                        // Set the desiredPresentTime:
14308a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                        ALOGV(
14318a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                            "Calling "
14328a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                            "native_window_set_buffers_timestamp(%" PRId64 ")",
14338a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                            time->desiredPresentTime);
14348a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                        native_window_set_buffers_timestamp(
14358a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                            window,
14368a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                            static_cast<int64_t>(time->desiredPresentTime));
14378a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott                    }
14384c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott                }
1439fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes
1440dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                err = window->queueBuffer(window, img.buffer.get(), fence);
1441dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                // queueBuffer always closes fence, even on error
1442dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                if (err != 0) {
1443dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    // TODO(jessehall): What now? We should probably cancel the
1444dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    // buffer, I guess?
1445dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
1446dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    swapchain_result = WorstPresentResult(
1447dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                        swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
1448dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                }
1449dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                if (img.dequeue_fence >= 0) {
1450dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    close(img.dequeue_fence);
1451dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                    img.dequeue_fence = -1;
1452dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                }
1453dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                img.dequeued = false;
1454fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes
1455fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                // If the swapchain is in shared mode, immediately dequeue the
1456fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                // buffer so it can be presented again without an intervening
1457fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                // call to AcquireNextImageKHR. We expect to get the same buffer
1458fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                // back from every call to dequeueBuffer in this mode.
1459fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                if (swapchain.shared && swapchain_result == VK_SUCCESS) {
1460fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                    ANativeWindowBuffer* buffer;
1461fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                    int fence_fd;
1462fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                    err = window->dequeueBuffer(window, &buffer, &fence_fd);
1463fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                    if (err != 0) {
1464fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                        ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
1465fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                        swapchain_result = WorstPresentResult(swapchain_result,
1466fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                            VK_ERROR_SURFACE_LOST_KHR);
1467fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                    }
1468fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                    else if (img.buffer != buffer) {
1469fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                        ALOGE("got wrong image back for shared swapchain");
1470fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                        swapchain_result = WorstPresentResult(swapchain_result,
1471fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                            VK_ERROR_SURFACE_LOST_KHR);
1472fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                    }
1473fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                    else {
1474fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                        img.dequeue_fence = fence_fd;
1475fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                        img.dequeued = true;
1476fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                    }
1477fca0f29e100d60163d408439f1a5750c353c9adeChris Forbes                }
1478dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            }
1479dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            if (swapchain_result != VK_SUCCESS) {
1480dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                ReleaseSwapchainImage(device, window, fence, img);
1481dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall                OrphanSwapchain(device, &swapchain);
1482dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            }
1483dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        } else {
1484dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            ReleaseSwapchainImage(device, nullptr, fence, img);
1485dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            swapchain_result = VK_ERROR_OUT_OF_DATE_KHR;
1486d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall        }
1487d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1488a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall        if (present_info->pResults)
1489dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            present_info->pResults[sc] = swapchain_result;
1490dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall
1491dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall        if (swapchain_result != final_result)
1492dc22507e6fd6659c886aa1218f7681fd43b74598Jesse Hall            final_result = WorstPresentResult(final_result, swapchain_result);
1493d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    }
1494cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    if (rects) {
1495cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott        allocator->pfnFree(allocator->pUserData, rects);
1496cb35113761ae7afc26c7bffc529b590575a9f4d7Ian Elliott    }
1497d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall
1498d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall    return final_result;
1499d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}
1500b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall
15014c8bb2a95d7849c79dea889f1be59281f4e374bfIan ElliottVKAPI_ATTR
15024c8bb2a95d7849c79dea889f1be59281f4e374bfIan ElliottVkResult GetRefreshCycleDurationGOOGLE(
15034c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    VkDevice,
150462c48c931f88ec44c41621afe988c34cab1fb41dIan Elliott    VkSwapchainKHR swapchain_handle,
15054c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
150662c48c931f88ec44c41621afe988c34cab1fb41dIan Elliott    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
15074c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    VkResult result = VK_SUCCESS;
15084c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott
1509dc96fdfa58260867c993fff78611220874753201Brian Anderson    pDisplayTimingProperties->refreshDuration =
1510dc96fdfa58260867c993fff78611220874753201Brian Anderson            static_cast<uint64_t>(swapchain.refresh_duration);
15114c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott
15124c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    return result;
15134c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott}
15144c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott
15154c8bb2a95d7849c79dea889f1be59281f4e374bfIan ElliottVKAPI_ATTR
15164c8bb2a95d7849c79dea889f1be59281f4e374bfIan ElliottVkResult GetPastPresentationTimingGOOGLE(
15174c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    VkDevice,
15184c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    VkSwapchainKHR swapchain_handle,
15194c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    uint32_t* count,
15204c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    VkPastPresentationTimingGOOGLE* timings) {
15214c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
15224c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    ANativeWindow* window = swapchain.surface.window.get();
15234c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    VkResult result = VK_SUCCESS;
15244c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott
15254c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    if (!swapchain.frame_timestamps_enabled) {
15268a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        ALOGV("Calling native_window_enable_frame_timestamps(true)");
15274c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott        native_window_enable_frame_timestamps(window, true);
15284c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott        swapchain.frame_timestamps_enabled = true;
15294c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    }
15304c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott
15314c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    if (timings) {
15328a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        // TODO(ianelliott): plumb return value (e.g. VK_INCOMPLETE)
15338a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        copy_ready_timings(swapchain, count, timings);
15344c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    } else {
15358a977261a012b0b02c062ac4a5a133f79ef74b62Ian Elliott        *count = get_num_ready_timings(swapchain);
15364c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    }
15374c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott
15384c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott    return result;
15394c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott}
15404c8bb2a95d7849c79dea889f1be59281f4e374bfIan Elliott
15410f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris ForbesVKAPI_ATTR
15420f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris ForbesVkResult GetSwapchainStatusKHR(
15430f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris Forbes    VkDevice,
15444e18ba82847bdb31504a1b005370f8df931f959dChris Forbes    VkSwapchainKHR swapchain_handle) {
15454e18ba82847bdb31504a1b005370f8df931f959dChris Forbes    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
15460f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris Forbes    VkResult result = VK_SUCCESS;
15470f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris Forbes
15484e18ba82847bdb31504a1b005370f8df931f959dChris Forbes    if (swapchain.surface.swapchain_handle != swapchain_handle) {
15494e18ba82847bdb31504a1b005370f8df931f959dChris Forbes        return VK_ERROR_OUT_OF_DATE_KHR;
15504e18ba82847bdb31504a1b005370f8df931f959dChris Forbes    }
15514e18ba82847bdb31504a1b005370f8df931f959dChris Forbes
15520f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris Forbes    // TODO(chrisforbes): Implement this function properly
15530f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris Forbes
15540f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris Forbes    return result;
15550f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris Forbes}
15560f2ac2e52d06ed171f7b888870c1c3c42b167d1aChris Forbes
1557d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney GoeltzenleuchterVKAPI_ATTR void SetHdrMetadataEXT(
1558d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    VkDevice device,
1559d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    uint32_t swapchainCount,
1560d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    const VkSwapchainKHR* pSwapchains,
1561d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    const VkHdrMetadataEXT* pHdrMetadataEXTs) {
1562d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    // TODO: courtneygo: implement actual function
1563d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    (void)device;
1564d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    (void)swapchainCount;
1565d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    (void)pSwapchains;
1566d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    (void)pHdrMetadataEXTs;
1567d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter    return;
1568d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter}
1569d634c483bcbd564acd81dcf5d15fc5fa8ab410f4Courtney Goeltzenleuchter
1570622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu}  // namespace driver
1571b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall}  // namespace vulkan
1572