Home | History | Annotate | Download | only in libvulkan
      1 /*
      2  * Copyright 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
     18 
     19 #include <android/hardware/graphics/common/1.0/types.h>
     20 #include <grallocusage/GrallocUsageConversion.h>
     21 #include <log/log.h>
     22 #include <sync/sync.h>
     23 #include <system/window.h>
     24 #include <ui/BufferQueueDefs.h>
     25 #include <utils/StrongPointer.h>
     26 #include <utils/Trace.h>
     27 #include <utils/Vector.h>
     28 
     29 #include <algorithm>
     30 #include <unordered_set>
     31 #include <vector>
     32 
     33 #include "driver.h"
     34 
     35 using android::hardware::graphics::common::V1_0::BufferUsage;
     36 
     37 // TODO(jessehall): Currently we don't have a good error code for when a native
     38 // window operation fails. Just returning INITIALIZATION_FAILED for now. Later
     39 // versions (post SDK 0.9) of the API/extension have a better error code.
     40 // When updating to that version, audit all error returns.
     41 namespace vulkan {
     42 namespace driver {
     43 
     44 namespace {
     45 
     46 const VkSurfaceTransformFlagsKHR kSupportedTransforms =
     47     VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR |
     48     VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
     49     VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR |
     50     VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR |
     51     // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
     52     // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
     53     // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
     54     // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
     55     // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
     56     VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
     57 
     58 int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) {
     59     switch (transform) {
     60         // TODO: See TODO in TranslateNativeToVulkanTransform
     61         case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
     62             return NATIVE_WINDOW_TRANSFORM_ROT_90;
     63         case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
     64             return NATIVE_WINDOW_TRANSFORM_ROT_180;
     65         case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
     66             return NATIVE_WINDOW_TRANSFORM_ROT_270;
     67         case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
     68         case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
     69         default:
     70             return 0;
     71     }
     72 }
     73 
     74 VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) {
     75     // Native and Vulkan transforms are isomorphic, but are represented
     76     // differently. Vulkan transforms are built up of an optional horizontal
     77     // mirror, followed by a clockwise 0/90/180/270-degree rotation. Native
     78     // transforms are built up from a horizontal flip, vertical flip, and
     79     // 90-degree rotation, all optional but always in that order.
     80 
     81     // TODO(jessehall): For now, only support pure rotations, not
     82     // flip or flip-and-rotate, until I have more time to test them and build
     83     // sample code. As far as I know we never actually use anything besides
     84     // pure rotations anyway.
     85 
     86     switch (native) {
     87         case 0:  // 0x0
     88             return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
     89         // case NATIVE_WINDOW_TRANSFORM_FLIP_H:  // 0x1
     90         //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
     91         // case NATIVE_WINDOW_TRANSFORM_FLIP_V:  // 0x2
     92         //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
     93         case NATIVE_WINDOW_TRANSFORM_ROT_180:  // FLIP_H | FLIP_V
     94             return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
     95         case NATIVE_WINDOW_TRANSFORM_ROT_90:  // 0x4
     96             return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
     97         // case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
     98         //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
     99         // case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
    100         //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
    101         case NATIVE_WINDOW_TRANSFORM_ROT_270:  // FLIP_H | FLIP_V | ROT_90
    102             return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
    103         case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
    104         default:
    105             return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
    106     }
    107 }
    108 
    109 int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) {
    110     switch (transform) {
    111         case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
    112             return NATIVE_WINDOW_TRANSFORM_ROT_270;
    113         case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
    114             return NATIVE_WINDOW_TRANSFORM_ROT_180;
    115         case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
    116             return NATIVE_WINDOW_TRANSFORM_ROT_90;
    117         // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
    118         // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
    119         //     return NATIVE_WINDOW_TRANSFORM_FLIP_H;
    120         // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
    121         //     return NATIVE_WINDOW_TRANSFORM_FLIP_H |
    122         //            NATIVE_WINDOW_TRANSFORM_ROT_90;
    123         // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
    124         //     return NATIVE_WINDOW_TRANSFORM_FLIP_V;
    125         // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
    126         //     return NATIVE_WINDOW_TRANSFORM_FLIP_V |
    127         //            NATIVE_WINDOW_TRANSFORM_ROT_90;
    128         case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
    129         case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
    130         default:
    131             return 0;
    132     }
    133 }
    134 
    135 class TimingInfo {
    136    public:
    137     TimingInfo() = default;
    138     TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId)
    139         : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
    140           native_frame_id_(nativeFrameId) {}
    141     bool ready() const {
    142         return (timestamp_desired_present_time_ !=
    143                         NATIVE_WINDOW_TIMESTAMP_PENDING &&
    144                 timestamp_actual_present_time_ !=
    145                         NATIVE_WINDOW_TIMESTAMP_PENDING &&
    146                 timestamp_render_complete_time_ !=
    147                         NATIVE_WINDOW_TIMESTAMP_PENDING &&
    148                 timestamp_composition_latch_time_ !=
    149                         NATIVE_WINDOW_TIMESTAMP_PENDING);
    150     }
    151     void calculate(int64_t rdur) {
    152         bool anyTimestampInvalid =
    153                 (timestamp_actual_present_time_ ==
    154                         NATIVE_WINDOW_TIMESTAMP_INVALID) ||
    155                 (timestamp_render_complete_time_ ==
    156                         NATIVE_WINDOW_TIMESTAMP_INVALID) ||
    157                 (timestamp_composition_latch_time_ ==
    158                         NATIVE_WINDOW_TIMESTAMP_INVALID);
    159         if (anyTimestampInvalid) {
    160             ALOGE("Unexpectedly received invalid timestamp.");
    161             vals_.actualPresentTime = 0;
    162             vals_.earliestPresentTime = 0;
    163             vals_.presentMargin = 0;
    164             return;
    165         }
    166 
    167         vals_.actualPresentTime =
    168                 static_cast<uint64_t>(timestamp_actual_present_time_);
    169         int64_t margin = (timestamp_composition_latch_time_ -
    170                            timestamp_render_complete_time_);
    171         // Calculate vals_.earliestPresentTime, and potentially adjust
    172         // vals_.presentMargin.  The initial value of vals_.earliestPresentTime
    173         // is vals_.actualPresentTime.  If we can subtract rdur (the duration
    174         // of a refresh cycle) from vals_.earliestPresentTime (and also from
    175         // vals_.presentMargin) and still leave a positive margin, then we can
    176         // report to the application that it could have presented earlier than
    177         // it did (per the extension specification).  If for some reason, we
    178         // can do this subtraction repeatedly, we do, since
    179         // vals_.earliestPresentTime really is supposed to be the "earliest".
    180         int64_t early_time = timestamp_actual_present_time_;
    181         while ((margin > rdur) &&
    182                ((early_time - rdur) > timestamp_composition_latch_time_)) {
    183             early_time -= rdur;
    184             margin -= rdur;
    185         }
    186         vals_.earliestPresentTime = static_cast<uint64_t>(early_time);
    187         vals_.presentMargin = static_cast<uint64_t>(margin);
    188     }
    189     void get_values(VkPastPresentationTimingGOOGLE* values) const {
    190         *values = vals_;
    191     }
    192 
    193    public:
    194     VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
    195 
    196     uint64_t native_frame_id_ { 0 };
    197     int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING };
    198     int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
    199     int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
    200     int64_t timestamp_composition_latch_time_
    201             { NATIVE_WINDOW_TIMESTAMP_PENDING };
    202 };
    203 
    204 // ----------------------------------------------------------------------------
    205 
    206 struct Surface {
    207     android::sp<ANativeWindow> window;
    208     VkSwapchainKHR swapchain_handle;
    209     uint64_t consumer_usage;
    210 };
    211 
    212 VkSurfaceKHR HandleFromSurface(Surface* surface) {
    213     return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface));
    214 }
    215 
    216 Surface* SurfaceFromHandle(VkSurfaceKHR handle) {
    217     return reinterpret_cast<Surface*>(handle);
    218 }
    219 
    220 // Maximum number of TimingInfo structs to keep per swapchain:
    221 enum { MAX_TIMING_INFOS = 10 };
    222 // Minimum number of frames to look for in the past (so we don't cause
    223 // syncronous requests to Surface Flinger):
    224 enum { MIN_NUM_FRAMES_AGO = 5 };
    225 
    226 struct Swapchain {
    227     Swapchain(Surface& surface_,
    228               uint32_t num_images_,
    229               VkPresentModeKHR present_mode,
    230               int pre_transform_)
    231         : surface(surface_),
    232           num_images(num_images_),
    233           mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR),
    234           pre_transform(pre_transform_),
    235           frame_timestamps_enabled(false),
    236           shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
    237                  present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
    238         ANativeWindow* window = surface.window.get();
    239         native_window_get_refresh_cycle_duration(
    240             window,
    241             &refresh_duration);
    242     }
    243     uint64_t get_refresh_duration()
    244     {
    245         ANativeWindow* window = surface.window.get();
    246         native_window_get_refresh_cycle_duration(
    247             window,
    248             &refresh_duration);
    249         return static_cast<uint64_t>(refresh_duration);
    250 
    251     }
    252 
    253     Surface& surface;
    254     uint32_t num_images;
    255     bool mailbox_mode;
    256     int pre_transform;
    257     bool frame_timestamps_enabled;
    258     int64_t refresh_duration;
    259     bool shared;
    260 
    261     struct Image {
    262         Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
    263         VkImage image;
    264         android::sp<ANativeWindowBuffer> buffer;
    265         // The fence is only valid when the buffer is dequeued, and should be
    266         // -1 any other time. When valid, we own the fd, and must ensure it is
    267         // closed: either by closing it explicitly when queueing the buffer,
    268         // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
    269         int dequeue_fence;
    270         bool dequeued;
    271     } images[android::BufferQueueDefs::NUM_BUFFER_SLOTS];
    272 
    273     android::Vector<TimingInfo> timing;
    274 };
    275 
    276 VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
    277     return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain));
    278 }
    279 
    280 Swapchain* SwapchainFromHandle(VkSwapchainKHR handle) {
    281     return reinterpret_cast<Swapchain*>(handle);
    282 }
    283 
    284 void ReleaseSwapchainImage(VkDevice device,
    285                            ANativeWindow* window,
    286                            int release_fence,
    287                            Swapchain::Image& image) {
    288     ALOG_ASSERT(release_fence == -1 || image.dequeued,
    289                 "ReleaseSwapchainImage: can't provide a release fence for "
    290                 "non-dequeued images");
    291 
    292     if (image.dequeued) {
    293         if (release_fence >= 0) {
    294             // We get here from vkQueuePresentKHR. The application is
    295             // responsible for creating an execution dependency chain from
    296             // vkAcquireNextImage (dequeue_fence) to vkQueuePresentKHR
    297             // (release_fence), so we can drop the dequeue_fence here.
    298             if (image.dequeue_fence >= 0)
    299                 close(image.dequeue_fence);
    300         } else {
    301             // We get here during swapchain destruction, or various serious
    302             // error cases e.g. when we can't create the release_fence during
    303             // vkQueuePresentKHR. In non-error cases, the dequeue_fence should
    304             // have already signalled, since the swapchain images are supposed
    305             // to be idle before the swapchain is destroyed. In error cases,
    306             // there may be rendering in flight to the image, but since we
    307             // weren't able to create a release_fence, waiting for the
    308             // dequeue_fence is about the best we can do.
    309             release_fence = image.dequeue_fence;
    310         }
    311         image.dequeue_fence = -1;
    312 
    313         if (window) {
    314             window->cancelBuffer(window, image.buffer.get(), release_fence);
    315         } else {
    316             if (release_fence >= 0) {
    317                 sync_wait(release_fence, -1 /* forever */);
    318                 close(release_fence);
    319             }
    320         }
    321 
    322         image.dequeued = false;
    323     }
    324 
    325     if (image.image) {
    326         GetData(device).driver.DestroyImage(device, image.image, nullptr);
    327         image.image = VK_NULL_HANDLE;
    328     }
    329 
    330     image.buffer.clear();
    331 }
    332 
    333 void OrphanSwapchain(VkDevice device, Swapchain* swapchain) {
    334     if (swapchain->surface.swapchain_handle != HandleFromSwapchain(swapchain))
    335         return;
    336     for (uint32_t i = 0; i < swapchain->num_images; i++) {
    337         if (!swapchain->images[i].dequeued)
    338             ReleaseSwapchainImage(device, nullptr, -1, swapchain->images[i]);
    339     }
    340     swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
    341     swapchain->timing.clear();
    342 }
    343 
    344 uint32_t get_num_ready_timings(Swapchain& swapchain) {
    345     if (swapchain.timing.size() < MIN_NUM_FRAMES_AGO) {
    346         return 0;
    347     }
    348 
    349     uint32_t num_ready = 0;
    350     const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1;
    351     for (uint32_t i = 0; i < num_timings; i++) {
    352         TimingInfo& ti = swapchain.timing.editItemAt(i);
    353         if (ti.ready()) {
    354             // This TimingInfo is ready to be reported to the user.  Add it
    355             // to the num_ready.
    356             num_ready++;
    357             continue;
    358         }
    359         // This TimingInfo is not yet ready to be reported to the user,
    360         // and so we should look for any available timestamps that
    361         // might make it ready.
    362         int64_t desired_present_time = 0;
    363         int64_t render_complete_time = 0;
    364         int64_t composition_latch_time = 0;
    365         int64_t actual_present_time = 0;
    366         // Obtain timestamps:
    367         int ret = native_window_get_frame_timestamps(
    368             swapchain.surface.window.get(), ti.native_frame_id_,
    369             &desired_present_time, &render_complete_time,
    370             &composition_latch_time,
    371             nullptr,  //&first_composition_start_time,
    372             nullptr,  //&last_composition_start_time,
    373             nullptr,  //&composition_finish_time,
    374             // TODO(ianelliott): Maybe ask if this one is
    375             // supported, at startup time (since it may not be
    376             // supported):
    377             &actual_present_time,
    378             nullptr,  //&dequeue_ready_time,
    379             nullptr /*&reads_done_time*/);
    380 
    381         if (ret != android::NO_ERROR) {
    382             continue;
    383         }
    384 
    385         // Record the timestamp(s) we received, and then see if this TimingInfo
    386         // is ready to be reported to the user:
    387         ti.timestamp_desired_present_time_ = desired_present_time;
    388         ti.timestamp_actual_present_time_ = actual_present_time;
    389         ti.timestamp_render_complete_time_ = render_complete_time;
    390         ti.timestamp_composition_latch_time_ = composition_latch_time;
    391 
    392         if (ti.ready()) {
    393             // The TimingInfo has received enough timestamps, and should now
    394             // use those timestamps to calculate the info that should be
    395             // reported to the user:
    396             ti.calculate(swapchain.refresh_duration);
    397             num_ready++;
    398         }
    399     }
    400     return num_ready;
    401 }
    402 
    403 // TODO(ianelliott): DEAL WITH RETURN VALUE (e.g. VK_INCOMPLETE)!!!
    404 void copy_ready_timings(Swapchain& swapchain,
    405                         uint32_t* count,
    406                         VkPastPresentationTimingGOOGLE* timings) {
    407     if (swapchain.timing.empty()) {
    408         *count = 0;
    409         return;
    410     }
    411 
    412     size_t last_ready = swapchain.timing.size() - 1;
    413     while (!swapchain.timing[last_ready].ready()) {
    414         if (last_ready == 0) {
    415             *count = 0;
    416             return;
    417         }
    418         last_ready--;
    419     }
    420 
    421     uint32_t num_copied = 0;
    422     size_t num_to_remove = 0;
    423     for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) {
    424         const TimingInfo& ti = swapchain.timing[i];
    425         if (ti.ready()) {
    426             ti.get_values(&timings[num_copied]);
    427             num_copied++;
    428         }
    429         num_to_remove++;
    430     }
    431 
    432     // Discard old frames that aren't ready if newer frames are ready.
    433     // We don't expect to get the timing info for those old frames.
    434     swapchain.timing.removeItemsAt(0, num_to_remove);
    435 
    436     *count = num_copied;
    437 }
    438 
    439 android_pixel_format GetNativePixelFormat(VkFormat format) {
    440     android_pixel_format native_format = HAL_PIXEL_FORMAT_RGBA_8888;
    441     switch (format) {
    442         case VK_FORMAT_R8G8B8A8_UNORM:
    443         case VK_FORMAT_R8G8B8A8_SRGB:
    444             native_format = HAL_PIXEL_FORMAT_RGBA_8888;
    445             break;
    446         case VK_FORMAT_R5G6B5_UNORM_PACK16:
    447             native_format = HAL_PIXEL_FORMAT_RGB_565;
    448             break;
    449         case VK_FORMAT_R16G16B16A16_SFLOAT:
    450             native_format = HAL_PIXEL_FORMAT_RGBA_FP16;
    451             break;
    452         case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
    453             native_format = HAL_PIXEL_FORMAT_RGBA_1010102;
    454             break;
    455         default:
    456             ALOGV("unsupported swapchain format %d", format);
    457             break;
    458     }
    459     return native_format;
    460 }
    461 
    462 android_dataspace GetNativeDataspace(VkColorSpaceKHR colorspace) {
    463     switch (colorspace) {
    464         case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR:
    465             return HAL_DATASPACE_V0_SRGB;
    466         case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT:
    467             return HAL_DATASPACE_DISPLAY_P3;
    468         case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
    469             return HAL_DATASPACE_V0_SCRGB_LINEAR;
    470         case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT:
    471             return HAL_DATASPACE_V0_SCRGB;
    472         case VK_COLOR_SPACE_DCI_P3_LINEAR_EXT:
    473             return HAL_DATASPACE_DCI_P3_LINEAR;
    474         case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT:
    475             return HAL_DATASPACE_DCI_P3;
    476         case VK_COLOR_SPACE_BT709_LINEAR_EXT:
    477             return HAL_DATASPACE_V0_SRGB_LINEAR;
    478         case VK_COLOR_SPACE_BT709_NONLINEAR_EXT:
    479             return HAL_DATASPACE_V0_SRGB;
    480         case VK_COLOR_SPACE_BT2020_LINEAR_EXT:
    481             return HAL_DATASPACE_BT2020_LINEAR;
    482         case VK_COLOR_SPACE_HDR10_ST2084_EXT:
    483             return static_cast<android_dataspace>(
    484                 HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
    485                 HAL_DATASPACE_RANGE_FULL);
    486         case VK_COLOR_SPACE_DOLBYVISION_EXT:
    487             return static_cast<android_dataspace>(
    488                 HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
    489                 HAL_DATASPACE_RANGE_FULL);
    490         case VK_COLOR_SPACE_HDR10_HLG_EXT:
    491             return static_cast<android_dataspace>(
    492                 HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_HLG |
    493                 HAL_DATASPACE_RANGE_FULL);
    494         case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT:
    495             return static_cast<android_dataspace>(
    496                 HAL_DATASPACE_STANDARD_ADOBE_RGB |
    497                 HAL_DATASPACE_TRANSFER_LINEAR | HAL_DATASPACE_RANGE_FULL);
    498         case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT:
    499             return HAL_DATASPACE_ADOBE_RGB;
    500 
    501         // Pass through is intended to allow app to provide data that is passed
    502         // to the display system without modification.
    503         case VK_COLOR_SPACE_PASS_THROUGH_EXT:
    504             return HAL_DATASPACE_ARBITRARY;
    505 
    506         default:
    507             // This indicates that we don't know about the
    508             // dataspace specified and we should indicate that
    509             // it's unsupported
    510             return HAL_DATASPACE_UNKNOWN;
    511     }
    512 }
    513 
    514 }  // anonymous namespace
    515 
    516 VKAPI_ATTR
    517 VkResult CreateAndroidSurfaceKHR(
    518     VkInstance instance,
    519     const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
    520     const VkAllocationCallbacks* allocator,
    521     VkSurfaceKHR* out_surface) {
    522     ATRACE_CALL();
    523 
    524     if (!allocator)
    525         allocator = &GetData(instance).allocator;
    526     void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Surface),
    527                                          alignof(Surface),
    528                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    529     if (!mem)
    530         return VK_ERROR_OUT_OF_HOST_MEMORY;
    531     Surface* surface = new (mem) Surface;
    532 
    533     surface->window = pCreateInfo->window;
    534     surface->swapchain_handle = VK_NULL_HANDLE;
    535     int err = native_window_get_consumer_usage(surface->window.get(),
    536                                                &surface->consumer_usage);
    537     if (err != android::NO_ERROR) {
    538         ALOGE("native_window_get_consumer_usage() failed: %s (%d)",
    539               strerror(-err), err);
    540         surface->~Surface();
    541         allocator->pfnFree(allocator->pUserData, surface);
    542         return VK_ERROR_INITIALIZATION_FAILED;
    543     }
    544 
    545     // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
    546     err =
    547         native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
    548     if (err != 0) {
    549         // TODO(jessehall): Improve error reporting. Can we enumerate possible
    550         // errors and translate them to valid Vulkan result codes?
    551         ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
    552               err);
    553         surface->~Surface();
    554         allocator->pfnFree(allocator->pUserData, surface);
    555         return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
    556     }
    557 
    558     *out_surface = HandleFromSurface(surface);
    559     return VK_SUCCESS;
    560 }
    561 
    562 VKAPI_ATTR
    563 void DestroySurfaceKHR(VkInstance instance,
    564                        VkSurfaceKHR surface_handle,
    565                        const VkAllocationCallbacks* allocator) {
    566     ATRACE_CALL();
    567 
    568     Surface* surface = SurfaceFromHandle(surface_handle);
    569     if (!surface)
    570         return;
    571     native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL);
    572     ALOGV_IF(surface->swapchain_handle != VK_NULL_HANDLE,
    573              "destroyed VkSurfaceKHR 0x%" PRIx64
    574              " has active VkSwapchainKHR 0x%" PRIx64,
    575              reinterpret_cast<uint64_t>(surface_handle),
    576              reinterpret_cast<uint64_t>(surface->swapchain_handle));
    577     surface->~Surface();
    578     if (!allocator)
    579         allocator = &GetData(instance).allocator;
    580     allocator->pfnFree(allocator->pUserData, surface);
    581 }
    582 
    583 VKAPI_ATTR
    584 VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
    585                                             uint32_t /*queue_family*/,
    586                                             VkSurfaceKHR surface_handle,
    587                                             VkBool32* supported) {
    588     ATRACE_CALL();
    589 
    590     const Surface* surface = SurfaceFromHandle(surface_handle);
    591     if (!surface) {
    592         return VK_ERROR_SURFACE_LOST_KHR;
    593     }
    594     const ANativeWindow* window = surface->window.get();
    595 
    596     int query_value;
    597     int err = window->query(window, NATIVE_WINDOW_FORMAT, &query_value);
    598     if (err != 0 || query_value < 0) {
    599         ALOGE("NATIVE_WINDOW_FORMAT query failed: %s (%d) value=%d",
    600               strerror(-err), err, query_value);
    601         return VK_ERROR_SURFACE_LOST_KHR;
    602     }
    603 
    604     android_pixel_format native_format =
    605         static_cast<android_pixel_format>(query_value);
    606 
    607     bool format_supported = false;
    608     switch (native_format) {
    609         case HAL_PIXEL_FORMAT_RGBA_8888:
    610         case HAL_PIXEL_FORMAT_RGB_565:
    611         case HAL_PIXEL_FORMAT_RGBA_FP16:
    612         case HAL_PIXEL_FORMAT_RGBA_1010102:
    613             format_supported = true;
    614             break;
    615         default:
    616             break;
    617     }
    618 
    619     *supported = static_cast<VkBool32>(
    620         format_supported || (surface->consumer_usage &
    621                              (AHARDWAREBUFFER_USAGE_CPU_READ_MASK |
    622                               AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) == 0);
    623 
    624     return VK_SUCCESS;
    625 }
    626 
    627 VKAPI_ATTR
    628 VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
    629     VkPhysicalDevice /*pdev*/,
    630     VkSurfaceKHR surface,
    631     VkSurfaceCapabilitiesKHR* capabilities) {
    632     ATRACE_CALL();
    633 
    634     int err;
    635     ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
    636 
    637     int width, height;
    638     err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
    639     if (err != 0) {
    640         ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
    641               strerror(-err), err);
    642         return VK_ERROR_SURFACE_LOST_KHR;
    643     }
    644     err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
    645     if (err != 0) {
    646         ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
    647               strerror(-err), err);
    648         return VK_ERROR_SURFACE_LOST_KHR;
    649     }
    650 
    651     int transform_hint;
    652     err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
    653     if (err != 0) {
    654         ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
    655               strerror(-err), err);
    656         return VK_ERROR_SURFACE_LOST_KHR;
    657     }
    658 
    659     // TODO(jessehall): Figure out what the min/max values should be.
    660     int max_buffer_count;
    661     err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &max_buffer_count);
    662     if (err != 0) {
    663         ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)",
    664               strerror(-err), err);
    665         return VK_ERROR_SURFACE_LOST_KHR;
    666     }
    667     capabilities->minImageCount = max_buffer_count == 1 ? 1 : 2;
    668     capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
    669 
    670     capabilities->currentExtent =
    671         VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
    672 
    673     // TODO(jessehall): Figure out what the max extent should be. Maximum
    674     // texture dimension maybe?
    675     capabilities->minImageExtent = VkExtent2D{1, 1};
    676     capabilities->maxImageExtent = VkExtent2D{4096, 4096};
    677 
    678     capabilities->maxImageArrayLayers = 1;
    679 
    680     capabilities->supportedTransforms = kSupportedTransforms;
    681     capabilities->currentTransform =
    682         TranslateNativeToVulkanTransform(transform_hint);
    683 
    684     // On Android, window composition is a WindowManager property, not something
    685     // associated with the bufferqueue. It can't be changed from here.
    686     capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
    687 
    688     // TODO(jessehall): I think these are right, but haven't thought hard about
    689     // it. Do we need to query the driver for support of any of these?
    690     // Currently not included:
    691     // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not
    692     // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not
    693     capabilities->supportedUsageFlags =
    694         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
    695         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
    696         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
    697         VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
    698 
    699     return VK_SUCCESS;
    700 }
    701 
    702 VKAPI_ATTR
    703 VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev,
    704                                             VkSurfaceKHR surface_handle,
    705                                             uint32_t* count,
    706                                             VkSurfaceFormatKHR* formats) {
    707     ATRACE_CALL();
    708 
    709     const InstanceData& instance_data = GetData(pdev);
    710 
    711     // TODO(jessehall): Fill out the set of supported formats. Longer term, add
    712     // a new gralloc method to query whether a (format, usage) pair is
    713     // supported, and check that for each gralloc format that corresponds to a
    714     // Vulkan format. Shorter term, just add a few more formats to the ones
    715     // hardcoded below.
    716 
    717     const VkSurfaceFormatKHR kFormats[] = {
    718         {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
    719         {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
    720         {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
    721         {VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
    722         {VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
    723     };
    724     const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
    725     uint32_t total_num_formats = kNumFormats;
    726 
    727     bool wide_color_support = false;
    728     Surface& surface = *SurfaceFromHandle(surface_handle);
    729     int err = native_window_get_wide_color_support(surface.window.get(),
    730                                                    &wide_color_support);
    731     if (err) {
    732         // Not allowed to return a more sensible error code, so do this
    733         return VK_ERROR_OUT_OF_HOST_MEMORY;
    734     }
    735     ALOGV("wide_color_support is: %d", wide_color_support);
    736     wide_color_support =
    737         wide_color_support &&
    738         instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
    739 
    740     const VkSurfaceFormatKHR kWideColorFormats[] = {
    741         {VK_FORMAT_R8G8B8A8_UNORM,
    742          VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
    743         {VK_FORMAT_R8G8B8A8_SRGB,
    744          VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
    745         {VK_FORMAT_R16G16B16A16_SFLOAT,
    746          VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT},
    747         {VK_FORMAT_R16G16B16A16_SFLOAT,
    748          VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT},
    749         {VK_FORMAT_A2B10G10R10_UNORM_PACK32,
    750          VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
    751     };
    752     const uint32_t kNumWideColorFormats =
    753         sizeof(kWideColorFormats) / sizeof(kWideColorFormats[0]);
    754     if (wide_color_support) {
    755         total_num_formats += kNumWideColorFormats;
    756     }
    757 
    758     VkResult result = VK_SUCCESS;
    759     if (formats) {
    760         uint32_t out_count = 0;
    761         uint32_t transfer_count = 0;
    762         if (*count < total_num_formats)
    763             result = VK_INCOMPLETE;
    764         transfer_count = std::min(*count, kNumFormats);
    765         std::copy(kFormats, kFormats + transfer_count, formats);
    766         out_count += transfer_count;
    767         if (wide_color_support) {
    768             transfer_count = std::min(*count - out_count, kNumWideColorFormats);
    769             std::copy(kWideColorFormats, kWideColorFormats + transfer_count,
    770                       formats + out_count);
    771             out_count += transfer_count;
    772         }
    773         *count = out_count;
    774     } else {
    775         *count = total_num_formats;
    776     }
    777     return result;
    778 }
    779 
    780 VKAPI_ATTR
    781 VkResult GetPhysicalDeviceSurfaceCapabilities2KHR(
    782     VkPhysicalDevice physicalDevice,
    783     const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
    784     VkSurfaceCapabilities2KHR* pSurfaceCapabilities) {
    785     ATRACE_CALL();
    786 
    787     VkResult result = GetPhysicalDeviceSurfaceCapabilitiesKHR(
    788         physicalDevice, pSurfaceInfo->surface,
    789         &pSurfaceCapabilities->surfaceCapabilities);
    790 
    791     VkSurfaceCapabilities2KHR* caps = pSurfaceCapabilities;
    792     while (caps->pNext) {
    793         caps = reinterpret_cast<VkSurfaceCapabilities2KHR*>(caps->pNext);
    794 
    795         switch (caps->sType) {
    796             case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: {
    797                 VkSharedPresentSurfaceCapabilitiesKHR* shared_caps =
    798                     reinterpret_cast<VkSharedPresentSurfaceCapabilitiesKHR*>(
    799                         caps);
    800                 // Claim same set of usage flags are supported for
    801                 // shared present modes as for other modes.
    802                 shared_caps->sharedPresentSupportedUsageFlags =
    803                     pSurfaceCapabilities->surfaceCapabilities
    804                         .supportedUsageFlags;
    805             } break;
    806 
    807             default:
    808                 // Ignore all other extension structs
    809                 break;
    810         }
    811     }
    812 
    813     return result;
    814 }
    815 
    816 VKAPI_ATTR
    817 VkResult GetPhysicalDeviceSurfaceFormats2KHR(
    818     VkPhysicalDevice physicalDevice,
    819     const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
    820     uint32_t* pSurfaceFormatCount,
    821     VkSurfaceFormat2KHR* pSurfaceFormats) {
    822     ATRACE_CALL();
    823 
    824     if (!pSurfaceFormats) {
    825         return GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice,
    826                                                   pSurfaceInfo->surface,
    827                                                   pSurfaceFormatCount, nullptr);
    828     } else {
    829         // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
    830         // after the call.
    831         android::Vector<VkSurfaceFormatKHR> surface_formats;
    832         surface_formats.resize(*pSurfaceFormatCount);
    833         VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
    834             physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
    835             &surface_formats.editItemAt(0));
    836 
    837         if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
    838             // marshal results individually due to stride difference.
    839             // completely ignore any chained extension structs.
    840             uint32_t formats_to_marshal = *pSurfaceFormatCount;
    841             for (uint32_t i = 0u; i < formats_to_marshal; i++) {
    842                 pSurfaceFormats[i].surfaceFormat = surface_formats[i];
    843             }
    844         }
    845 
    846         return result;
    847     }
    848 }
    849 
    850 VKAPI_ATTR
    851 VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev,
    852                                                  VkSurfaceKHR surface,
    853                                                  uint32_t* count,
    854                                                  VkPresentModeKHR* modes) {
    855     ATRACE_CALL();
    856 
    857     int err;
    858     int query_value;
    859     ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
    860 
    861     err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
    862     if (err != 0 || query_value < 0) {
    863         ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) value=%d",
    864               strerror(-err), err, query_value);
    865         return VK_ERROR_SURFACE_LOST_KHR;
    866     }
    867     uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
    868 
    869     err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
    870     if (err != 0 || query_value < 0) {
    871         ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d",
    872               strerror(-err), err, query_value);
    873         return VK_ERROR_SURFACE_LOST_KHR;
    874     }
    875     uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
    876 
    877     android::Vector<VkPresentModeKHR> present_modes;
    878     if (min_undequeued_buffers + 1 < max_buffer_count)
    879         present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
    880     present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
    881 
    882     VkPhysicalDevicePresentationPropertiesANDROID present_properties;
    883     if (QueryPresentationProperties(pdev, &present_properties)) {
    884         if (present_properties.sharedImage) {
    885             present_modes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR);
    886             present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
    887         }
    888     }
    889 
    890     uint32_t num_modes = uint32_t(present_modes.size());
    891 
    892     VkResult result = VK_SUCCESS;
    893     if (modes) {
    894         if (*count < num_modes)
    895             result = VK_INCOMPLETE;
    896         *count = std::min(*count, num_modes);
    897         std::copy(present_modes.begin(), present_modes.begin() + int(*count), modes);
    898     } else {
    899         *count = num_modes;
    900     }
    901     return result;
    902 }
    903 
    904 VKAPI_ATTR
    905 VkResult GetDeviceGroupPresentCapabilitiesKHR(
    906     VkDevice,
    907     VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
    908     ATRACE_CALL();
    909 
    910     ALOGV_IF(pDeviceGroupPresentCapabilities->sType !=
    911                  VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR,
    912              "vkGetDeviceGroupPresentCapabilitiesKHR: invalid "
    913              "VkDeviceGroupPresentCapabilitiesKHR structure type %d",
    914              pDeviceGroupPresentCapabilities->sType);
    915 
    916     memset(pDeviceGroupPresentCapabilities->presentMask, 0,
    917            sizeof(pDeviceGroupPresentCapabilities->presentMask));
    918 
    919     // assume device group of size 1
    920     pDeviceGroupPresentCapabilities->presentMask[0] = 1 << 0;
    921     pDeviceGroupPresentCapabilities->modes =
    922         VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
    923 
    924     return VK_SUCCESS;
    925 }
    926 
    927 VKAPI_ATTR
    928 VkResult GetDeviceGroupSurfacePresentModesKHR(
    929     VkDevice,
    930     VkSurfaceKHR,
    931     VkDeviceGroupPresentModeFlagsKHR* pModes) {
    932     ATRACE_CALL();
    933 
    934     *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
    935     return VK_SUCCESS;
    936 }
    937 
    938 VKAPI_ATTR
    939 VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice,
    940                                                VkSurfaceKHR surface,
    941                                                uint32_t* pRectCount,
    942                                                VkRect2D* pRects) {
    943     ATRACE_CALL();
    944 
    945     if (!pRects) {
    946         *pRectCount = 1;
    947     } else {
    948         uint32_t count = std::min(*pRectCount, 1u);
    949         bool incomplete = *pRectCount < 1;
    950 
    951         *pRectCount = count;
    952 
    953         if (incomplete) {
    954             return VK_INCOMPLETE;
    955         }
    956 
    957         int err;
    958         ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
    959 
    960         int width = 0, height = 0;
    961         err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
    962         if (err != 0) {
    963             ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
    964                   strerror(-err), err);
    965         }
    966         err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
    967         if (err != 0) {
    968             ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
    969                   strerror(-err), err);
    970         }
    971 
    972         // TODO: Return something better than "whole window"
    973         pRects[0].offset.x = 0;
    974         pRects[0].offset.y = 0;
    975         pRects[0].extent = VkExtent2D{static_cast<uint32_t>(width),
    976                                       static_cast<uint32_t>(height)};
    977     }
    978     return VK_SUCCESS;
    979 }
    980 
    981 VKAPI_ATTR
    982 VkResult CreateSwapchainKHR(VkDevice device,
    983                             const VkSwapchainCreateInfoKHR* create_info,
    984                             const VkAllocationCallbacks* allocator,
    985                             VkSwapchainKHR* swapchain_handle) {
    986     ATRACE_CALL();
    987 
    988     int err;
    989     VkResult result = VK_SUCCESS;
    990 
    991     ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
    992           " minImageCount=%u imageFormat=%u imageColorSpace=%u"
    993           " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
    994           " oldSwapchain=0x%" PRIx64,
    995           reinterpret_cast<uint64_t>(create_info->surface),
    996           create_info->minImageCount, create_info->imageFormat,
    997           create_info->imageColorSpace, create_info->imageExtent.width,
    998           create_info->imageExtent.height, create_info->imageUsage,
    999           create_info->preTransform, create_info->presentMode,
   1000           reinterpret_cast<uint64_t>(create_info->oldSwapchain));
   1001 
   1002     if (!allocator)
   1003         allocator = &GetData(device).allocator;
   1004 
   1005     android_pixel_format native_pixel_format =
   1006         GetNativePixelFormat(create_info->imageFormat);
   1007     android_dataspace native_dataspace =
   1008         GetNativeDataspace(create_info->imageColorSpace);
   1009     if (native_dataspace == HAL_DATASPACE_UNKNOWN) {
   1010         ALOGE(
   1011             "CreateSwapchainKHR(VkSwapchainCreateInfoKHR.imageColorSpace = %d) "
   1012             "failed: Unsupported color space",
   1013             create_info->imageColorSpace);
   1014         return VK_ERROR_INITIALIZATION_FAILED;
   1015     }
   1016 
   1017     ALOGV_IF(create_info->imageArrayLayers != 1,
   1018              "swapchain imageArrayLayers=%u not supported",
   1019              create_info->imageArrayLayers);
   1020     ALOGV_IF((create_info->preTransform & ~kSupportedTransforms) != 0,
   1021              "swapchain preTransform=%#x not supported",
   1022              create_info->preTransform);
   1023     ALOGV_IF(!(create_info->presentMode == VK_PRESENT_MODE_FIFO_KHR ||
   1024                create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ||
   1025                create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
   1026                create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR),
   1027              "swapchain presentMode=%u not supported",
   1028              create_info->presentMode);
   1029 
   1030     Surface& surface = *SurfaceFromHandle(create_info->surface);
   1031 
   1032     if (surface.swapchain_handle != create_info->oldSwapchain) {
   1033         ALOGV("Can't create a swapchain for VkSurfaceKHR 0x%" PRIx64
   1034               " because it already has active swapchain 0x%" PRIx64
   1035               " but VkSwapchainCreateInfo::oldSwapchain=0x%" PRIx64,
   1036               reinterpret_cast<uint64_t>(create_info->surface),
   1037               reinterpret_cast<uint64_t>(surface.swapchain_handle),
   1038               reinterpret_cast<uint64_t>(create_info->oldSwapchain));
   1039         return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
   1040     }
   1041     if (create_info->oldSwapchain != VK_NULL_HANDLE)
   1042         OrphanSwapchain(device, SwapchainFromHandle(create_info->oldSwapchain));
   1043 
   1044     // -- Reset the native window --
   1045     // The native window might have been used previously, and had its properties
   1046     // changed from defaults. That will affect the answer we get for queries
   1047     // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we
   1048     // attempt such queries.
   1049 
   1050     // The native window only allows dequeueing all buffers before any have
   1051     // been queued, since after that point at least one is assumed to be in
   1052     // non-FREE state at any given time. Disconnecting and re-connecting
   1053     // orphans the previous buffers, getting us back to the state where we can
   1054     // dequeue all buffers.
   1055     err = native_window_api_disconnect(surface.window.get(),
   1056                                        NATIVE_WINDOW_API_EGL);
   1057     ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)",
   1058              strerror(-err), err);
   1059     err =
   1060         native_window_api_connect(surface.window.get(), NATIVE_WINDOW_API_EGL);
   1061     ALOGW_IF(err != 0, "native_window_api_connect failed: %s (%d)",
   1062              strerror(-err), err);
   1063 
   1064     err = native_window_set_buffer_count(surface.window.get(), 0);
   1065     if (err != 0) {
   1066         ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
   1067               strerror(-err), err);
   1068         return VK_ERROR_SURFACE_LOST_KHR;
   1069     }
   1070 
   1071     int swap_interval =
   1072         create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
   1073     err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
   1074     if (err != 0) {
   1075         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1076         // errors and translate them to valid Vulkan result codes?
   1077         ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
   1078               strerror(-err), err);
   1079         return VK_ERROR_SURFACE_LOST_KHR;
   1080     }
   1081 
   1082     err = native_window_set_shared_buffer_mode(surface.window.get(), false);
   1083     if (err != 0) {
   1084         ALOGE("native_window_set_shared_buffer_mode(false) failed: %s (%d)",
   1085               strerror(-err), err);
   1086         return VK_ERROR_SURFACE_LOST_KHR;
   1087     }
   1088 
   1089     err = native_window_set_auto_refresh(surface.window.get(), false);
   1090     if (err != 0) {
   1091         ALOGE("native_window_set_auto_refresh(false) failed: %s (%d)",
   1092               strerror(-err), err);
   1093         return VK_ERROR_SURFACE_LOST_KHR;
   1094     }
   1095 
   1096     // -- Configure the native window --
   1097 
   1098     const auto& dispatch = GetData(device).driver;
   1099 
   1100     err = native_window_set_buffers_format(surface.window.get(),
   1101                                            native_pixel_format);
   1102     if (err != 0) {
   1103         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1104         // errors and translate them to valid Vulkan result codes?
   1105         ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
   1106               native_pixel_format, strerror(-err), err);
   1107         return VK_ERROR_SURFACE_LOST_KHR;
   1108     }
   1109     err = native_window_set_buffers_data_space(surface.window.get(),
   1110                                                native_dataspace);
   1111     if (err != 0) {
   1112         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1113         // errors and translate them to valid Vulkan result codes?
   1114         ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
   1115               native_dataspace, strerror(-err), err);
   1116         return VK_ERROR_SURFACE_LOST_KHR;
   1117     }
   1118 
   1119     err = native_window_set_buffers_dimensions(
   1120         surface.window.get(), static_cast<int>(create_info->imageExtent.width),
   1121         static_cast<int>(create_info->imageExtent.height));
   1122     if (err != 0) {
   1123         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1124         // errors and translate them to valid Vulkan result codes?
   1125         ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
   1126               create_info->imageExtent.width, create_info->imageExtent.height,
   1127               strerror(-err), err);
   1128         return VK_ERROR_SURFACE_LOST_KHR;
   1129     }
   1130 
   1131     // VkSwapchainCreateInfo::preTransform indicates the transformation the app
   1132     // applied during rendering. native_window_set_transform() expects the
   1133     // inverse: the transform the app is requesting that the compositor perform
   1134     // during composition. With native windows, pre-transform works by rendering
   1135     // with the same transform the compositor is applying (as in Vulkan), but
   1136     // then requesting the inverse transform, so that when the compositor does
   1137     // it's job the two transforms cancel each other out and the compositor ends
   1138     // up applying an identity transform to the app's buffer.
   1139     err = native_window_set_buffers_transform(
   1140         surface.window.get(),
   1141         InvertTransformToNative(create_info->preTransform));
   1142     if (err != 0) {
   1143         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1144         // errors and translate them to valid Vulkan result codes?
   1145         ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
   1146               InvertTransformToNative(create_info->preTransform),
   1147               strerror(-err), err);
   1148         return VK_ERROR_SURFACE_LOST_KHR;
   1149     }
   1150 
   1151     err = native_window_set_scaling_mode(
   1152         surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
   1153     if (err != 0) {
   1154         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1155         // errors and translate them to valid Vulkan result codes?
   1156         ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
   1157               strerror(-err), err);
   1158         return VK_ERROR_SURFACE_LOST_KHR;
   1159     }
   1160 
   1161     VkSwapchainImageUsageFlagsANDROID swapchain_image_usage = 0;
   1162     if (create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
   1163         create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
   1164         swapchain_image_usage |= VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID;
   1165         err = native_window_set_shared_buffer_mode(surface.window.get(), true);
   1166         if (err != 0) {
   1167             ALOGE("native_window_set_shared_buffer_mode failed: %s (%d)", strerror(-err), err);
   1168             return VK_ERROR_SURFACE_LOST_KHR;
   1169         }
   1170     }
   1171 
   1172     if (create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
   1173         err = native_window_set_auto_refresh(surface.window.get(), true);
   1174         if (err != 0) {
   1175             ALOGE("native_window_set_auto_refresh failed: %s (%d)", strerror(-err), err);
   1176             return VK_ERROR_SURFACE_LOST_KHR;
   1177         }
   1178     }
   1179 
   1180     int query_value;
   1181     err = surface.window->query(surface.window.get(),
   1182                                 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
   1183                                 &query_value);
   1184     if (err != 0 || query_value < 0) {
   1185         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1186         // errors and translate them to valid Vulkan result codes?
   1187         ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
   1188               query_value);
   1189         return VK_ERROR_SURFACE_LOST_KHR;
   1190     }
   1191     uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
   1192     uint32_t num_images =
   1193         (swap_interval ? create_info->minImageCount
   1194                        : std::max(3u, create_info->minImageCount)) -
   1195         1 + min_undequeued_buffers;
   1196 
   1197     // Lower layer insists that we have at least two buffers. This is wasteful
   1198     // and we'd like to relax it in the shared case, but not all the pieces are
   1199     // in place for that to work yet. Note we only lie to the lower layer-- we
   1200     // don't want to give the app back a swapchain with extra images (which they
   1201     // can't actually use!).
   1202     err = native_window_set_buffer_count(surface.window.get(), std::max(2u, num_images));
   1203     if (err != 0) {
   1204         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1205         // errors and translate them to valid Vulkan result codes?
   1206         ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
   1207               strerror(-err), err);
   1208         return VK_ERROR_SURFACE_LOST_KHR;
   1209     }
   1210 
   1211     int32_t legacy_usage = 0;
   1212     if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
   1213         uint64_t consumer_usage, producer_usage;
   1214         ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsage2ANDROID");
   1215         result = dispatch.GetSwapchainGrallocUsage2ANDROID(
   1216             device, create_info->imageFormat, create_info->imageUsage,
   1217             swapchain_image_usage, &consumer_usage, &producer_usage);
   1218         ATRACE_END();
   1219         if (result != VK_SUCCESS) {
   1220             ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
   1221             return VK_ERROR_SURFACE_LOST_KHR;
   1222         }
   1223         legacy_usage =
   1224             android_convertGralloc1To0Usage(producer_usage, consumer_usage);
   1225     } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
   1226         ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsageANDROID");
   1227         result = dispatch.GetSwapchainGrallocUsageANDROID(
   1228             device, create_info->imageFormat, create_info->imageUsage,
   1229             &legacy_usage);
   1230         ATRACE_END();
   1231         if (result != VK_SUCCESS) {
   1232             ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
   1233             return VK_ERROR_SURFACE_LOST_KHR;
   1234         }
   1235     }
   1236     uint64_t native_usage = static_cast<uint64_t>(legacy_usage);
   1237 
   1238     bool createProtectedSwapchain = false;
   1239     if (create_info->flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR) {
   1240         createProtectedSwapchain = true;
   1241         native_usage |= BufferUsage::PROTECTED;
   1242     }
   1243     err = native_window_set_usage(surface.window.get(), native_usage);
   1244     if (err != 0) {
   1245         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1246         // errors and translate them to valid Vulkan result codes?
   1247         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
   1248         return VK_ERROR_SURFACE_LOST_KHR;
   1249     }
   1250 
   1251     // -- Allocate our Swapchain object --
   1252     // After this point, we must deallocate the swapchain on error.
   1253 
   1254     void* mem = allocator->pfnAllocation(allocator->pUserData,
   1255                                          sizeof(Swapchain), alignof(Swapchain),
   1256                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
   1257     if (!mem)
   1258         return VK_ERROR_OUT_OF_HOST_MEMORY;
   1259     Swapchain* swapchain = new (mem)
   1260         Swapchain(surface, num_images, create_info->presentMode,
   1261                   TranslateVulkanToNativeTransform(create_info->preTransform));
   1262     // -- Dequeue all buffers and create a VkImage for each --
   1263     // Any failures during or after this must cancel the dequeued buffers.
   1264 
   1265     VkSwapchainImageCreateInfoANDROID swapchain_image_create = {
   1266 #pragma clang diagnostic push
   1267 #pragma clang diagnostic ignored "-Wold-style-cast"
   1268         .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID,
   1269 #pragma clang diagnostic pop
   1270         .pNext = nullptr,
   1271         .usage = swapchain_image_usage,
   1272     };
   1273     VkNativeBufferANDROID image_native_buffer = {
   1274 #pragma clang diagnostic push
   1275 #pragma clang diagnostic ignored "-Wold-style-cast"
   1276         .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
   1277 #pragma clang diagnostic pop
   1278         .pNext = &swapchain_image_create,
   1279     };
   1280     VkImageCreateInfo image_create = {
   1281         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
   1282         .pNext = &image_native_buffer,
   1283         .imageType = VK_IMAGE_TYPE_2D,
   1284         .format = create_info->imageFormat,
   1285         .extent = {0, 0, 1},
   1286         .mipLevels = 1,
   1287         .arrayLayers = 1,
   1288         .samples = VK_SAMPLE_COUNT_1_BIT,
   1289         .tiling = VK_IMAGE_TILING_OPTIMAL,
   1290         .usage = create_info->imageUsage,
   1291         .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
   1292         .sharingMode = create_info->imageSharingMode,
   1293         .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
   1294         .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
   1295     };
   1296 
   1297     for (uint32_t i = 0; i < num_images; i++) {
   1298         Swapchain::Image& img = swapchain->images[i];
   1299 
   1300         ANativeWindowBuffer* buffer;
   1301         err = surface.window->dequeueBuffer(surface.window.get(), &buffer,
   1302                                             &img.dequeue_fence);
   1303         if (err != 0) {
   1304             // TODO(jessehall): Improve error reporting. Can we enumerate
   1305             // possible errors and translate them to valid Vulkan result codes?
   1306             ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
   1307             result = VK_ERROR_SURFACE_LOST_KHR;
   1308             break;
   1309         }
   1310         img.buffer = buffer;
   1311         img.dequeued = true;
   1312 
   1313         image_create.extent =
   1314             VkExtent3D{static_cast<uint32_t>(img.buffer->width),
   1315                        static_cast<uint32_t>(img.buffer->height),
   1316                        1};
   1317         image_native_buffer.handle = img.buffer->handle;
   1318         image_native_buffer.stride = img.buffer->stride;
   1319         image_native_buffer.format = img.buffer->format;
   1320         image_native_buffer.usage = int(img.buffer->usage);
   1321         android_convertGralloc0To1Usage(int(img.buffer->usage),
   1322             &image_native_buffer.usage2.producer,
   1323             &image_native_buffer.usage2.consumer);
   1324 
   1325         ATRACE_BEGIN("dispatch.CreateImage");
   1326         result =
   1327             dispatch.CreateImage(device, &image_create, nullptr, &img.image);
   1328         ATRACE_END();
   1329         if (result != VK_SUCCESS) {
   1330             ALOGD("vkCreateImage w/ native buffer failed: %u", result);
   1331             break;
   1332         }
   1333     }
   1334 
   1335     // -- Cancel all buffers, returning them to the queue --
   1336     // If an error occurred before, also destroy the VkImage and release the
   1337     // buffer reference. Otherwise, we retain a strong reference to the buffer.
   1338     //
   1339     // TODO(jessehall): The error path here is the same as DestroySwapchain,
   1340     // but not the non-error path. Should refactor/unify.
   1341     for (uint32_t i = 0; i < num_images; i++) {
   1342         Swapchain::Image& img = swapchain->images[i];
   1343         if (img.dequeued) {
   1344             if (!swapchain->shared) {
   1345                 surface.window->cancelBuffer(surface.window.get(), img.buffer.get(),
   1346                                              img.dequeue_fence);
   1347                 img.dequeue_fence = -1;
   1348                 img.dequeued = false;
   1349             }
   1350         }
   1351         if (result != VK_SUCCESS) {
   1352             if (img.image) {
   1353                 ATRACE_BEGIN("dispatch.DestroyImage");
   1354                 dispatch.DestroyImage(device, img.image, nullptr);
   1355                 ATRACE_END();
   1356             }
   1357         }
   1358     }
   1359 
   1360     if (result != VK_SUCCESS) {
   1361         swapchain->~Swapchain();
   1362         allocator->pfnFree(allocator->pUserData, swapchain);
   1363         return result;
   1364     }
   1365 
   1366     surface.swapchain_handle = HandleFromSwapchain(swapchain);
   1367     *swapchain_handle = surface.swapchain_handle;
   1368     return VK_SUCCESS;
   1369 }
   1370 
   1371 VKAPI_ATTR
   1372 void DestroySwapchainKHR(VkDevice device,
   1373                          VkSwapchainKHR swapchain_handle,
   1374                          const VkAllocationCallbacks* allocator) {
   1375     ATRACE_CALL();
   1376 
   1377     const auto& dispatch = GetData(device).driver;
   1378     Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
   1379     if (!swapchain)
   1380         return;
   1381     bool active = swapchain->surface.swapchain_handle == swapchain_handle;
   1382     ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
   1383 
   1384     if (swapchain->frame_timestamps_enabled) {
   1385         native_window_enable_frame_timestamps(window, false);
   1386     }
   1387     for (uint32_t i = 0; i < swapchain->num_images; i++)
   1388         ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
   1389     if (active)
   1390         swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
   1391     if (!allocator)
   1392         allocator = &GetData(device).allocator;
   1393     swapchain->~Swapchain();
   1394     allocator->pfnFree(allocator->pUserData, swapchain);
   1395 }
   1396 
   1397 VKAPI_ATTR
   1398 VkResult GetSwapchainImagesKHR(VkDevice,
   1399                                VkSwapchainKHR swapchain_handle,
   1400                                uint32_t* count,
   1401                                VkImage* images) {
   1402     ATRACE_CALL();
   1403 
   1404     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
   1405     ALOGW_IF(swapchain.surface.swapchain_handle != swapchain_handle,
   1406              "getting images for non-active swapchain 0x%" PRIx64
   1407              "; only dequeued image handles are valid",
   1408              reinterpret_cast<uint64_t>(swapchain_handle));
   1409     VkResult result = VK_SUCCESS;
   1410     if (images) {
   1411         uint32_t n = swapchain.num_images;
   1412         if (*count < swapchain.num_images) {
   1413             n = *count;
   1414             result = VK_INCOMPLETE;
   1415         }
   1416         for (uint32_t i = 0; i < n; i++)
   1417             images[i] = swapchain.images[i].image;
   1418         *count = n;
   1419     } else {
   1420         *count = swapchain.num_images;
   1421     }
   1422     return result;
   1423 }
   1424 
   1425 VKAPI_ATTR
   1426 VkResult AcquireNextImageKHR(VkDevice device,
   1427                              VkSwapchainKHR swapchain_handle,
   1428                              uint64_t timeout,
   1429                              VkSemaphore semaphore,
   1430                              VkFence vk_fence,
   1431                              uint32_t* image_index) {
   1432     ATRACE_CALL();
   1433 
   1434     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
   1435     ANativeWindow* window = swapchain.surface.window.get();
   1436     VkResult result;
   1437     int err;
   1438 
   1439     if (swapchain.surface.swapchain_handle != swapchain_handle)
   1440         return VK_ERROR_OUT_OF_DATE_KHR;
   1441 
   1442     ALOGW_IF(
   1443         timeout != UINT64_MAX,
   1444         "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented");
   1445 
   1446     if (swapchain.shared) {
   1447         // In shared mode, we keep the buffer dequeued all the time, so we don't
   1448         // want to dequeue a buffer here. Instead, just ask the driver to ensure
   1449         // the semaphore and fence passed to us will be signalled.
   1450         *image_index = 0;
   1451         result = GetData(device).driver.AcquireImageANDROID(
   1452                 device, swapchain.images[*image_index].image, -1, semaphore, vk_fence);
   1453         return result;
   1454     }
   1455 
   1456     ANativeWindowBuffer* buffer;
   1457     int fence_fd;
   1458     err = window->dequeueBuffer(window, &buffer, &fence_fd);
   1459     if (err != 0) {
   1460         // TODO(jessehall): Improve error reporting. Can we enumerate possible
   1461         // errors and translate them to valid Vulkan result codes?
   1462         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
   1463         return VK_ERROR_SURFACE_LOST_KHR;
   1464     }
   1465 
   1466     uint32_t idx;
   1467     for (idx = 0; idx < swapchain.num_images; idx++) {
   1468         if (swapchain.images[idx].buffer.get() == buffer) {
   1469             swapchain.images[idx].dequeued = true;
   1470             swapchain.images[idx].dequeue_fence = fence_fd;
   1471             break;
   1472         }
   1473     }
   1474     if (idx == swapchain.num_images) {
   1475         ALOGE("dequeueBuffer returned unrecognized buffer");
   1476         window->cancelBuffer(window, buffer, fence_fd);
   1477         return VK_ERROR_OUT_OF_DATE_KHR;
   1478     }
   1479 
   1480     int fence_clone = -1;
   1481     if (fence_fd != -1) {
   1482         fence_clone = dup(fence_fd);
   1483         if (fence_clone == -1) {
   1484             ALOGE("dup(fence) failed, stalling until signalled: %s (%d)",
   1485                   strerror(errno), errno);
   1486             sync_wait(fence_fd, -1 /* forever */);
   1487         }
   1488     }
   1489 
   1490     result = GetData(device).driver.AcquireImageANDROID(
   1491         device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence);
   1492     if (result != VK_SUCCESS) {
   1493         // NOTE: we're relying on AcquireImageANDROID to close fence_clone,
   1494         // even if the call fails. We could close it ourselves on failure, but
   1495         // that would create a race condition if the driver closes it on a
   1496         // failure path: some other thread might create an fd with the same
   1497         // number between the time the driver closes it and the time we close
   1498         // it. We must assume one of: the driver *always* closes it even on
   1499         // failure, or *never* closes it on failure.
   1500         window->cancelBuffer(window, buffer, fence_fd);
   1501         swapchain.images[idx].dequeued = false;
   1502         swapchain.images[idx].dequeue_fence = -1;
   1503         return result;
   1504     }
   1505 
   1506     *image_index = idx;
   1507     return VK_SUCCESS;
   1508 }
   1509 
   1510 VKAPI_ATTR
   1511 VkResult AcquireNextImage2KHR(VkDevice device,
   1512                               const VkAcquireNextImageInfoKHR* pAcquireInfo,
   1513                               uint32_t* pImageIndex) {
   1514     ATRACE_CALL();
   1515 
   1516     // TODO: this should actually be the other way around and this function
   1517     // should handle any additional structures that get passed in
   1518     return AcquireNextImageKHR(device, pAcquireInfo->swapchain,
   1519                                pAcquireInfo->timeout, pAcquireInfo->semaphore,
   1520                                pAcquireInfo->fence, pImageIndex);
   1521 }
   1522 
   1523 static VkResult WorstPresentResult(VkResult a, VkResult b) {
   1524     // See the error ranking for vkQueuePresentKHR at the end of section 29.6
   1525     // (in spec version 1.0.14).
   1526     static const VkResult kWorstToBest[] = {
   1527         VK_ERROR_DEVICE_LOST,
   1528         VK_ERROR_SURFACE_LOST_KHR,
   1529         VK_ERROR_OUT_OF_DATE_KHR,
   1530         VK_ERROR_OUT_OF_DEVICE_MEMORY,
   1531         VK_ERROR_OUT_OF_HOST_MEMORY,
   1532         VK_SUBOPTIMAL_KHR,
   1533     };
   1534     for (auto result : kWorstToBest) {
   1535         if (a == result || b == result)
   1536             return result;
   1537     }
   1538     ALOG_ASSERT(a == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", a);
   1539     ALOG_ASSERT(b == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", b);
   1540     return a != VK_SUCCESS ? a : b;
   1541 }
   1542 
   1543 VKAPI_ATTR
   1544 VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
   1545     ATRACE_CALL();
   1546 
   1547     ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
   1548              "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
   1549              present_info->sType);
   1550 
   1551     VkDevice device = GetData(queue).driver_device;
   1552     const auto& dispatch = GetData(queue).driver;
   1553     VkResult final_result = VK_SUCCESS;
   1554 
   1555     // Look at the pNext chain for supported extension structs:
   1556     const VkPresentRegionsKHR* present_regions = nullptr;
   1557     const VkPresentTimesInfoGOOGLE* present_times = nullptr;
   1558     const VkPresentRegionsKHR* next =
   1559         reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext);
   1560     while (next) {
   1561         switch (next->sType) {
   1562             case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
   1563                 present_regions = next;
   1564                 break;
   1565             case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE:
   1566                 present_times =
   1567                     reinterpret_cast<const VkPresentTimesInfoGOOGLE*>(next);
   1568                 break;
   1569             default:
   1570                 ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x",
   1571                       next->sType);
   1572                 break;
   1573         }
   1574         next = reinterpret_cast<const VkPresentRegionsKHR*>(next->pNext);
   1575     }
   1576     ALOGV_IF(
   1577         present_regions &&
   1578             present_regions->swapchainCount != present_info->swapchainCount,
   1579         "VkPresentRegions::swapchainCount != VkPresentInfo::swapchainCount");
   1580     ALOGV_IF(present_times &&
   1581                  present_times->swapchainCount != present_info->swapchainCount,
   1582              "VkPresentTimesInfoGOOGLE::swapchainCount != "
   1583              "VkPresentInfo::swapchainCount");
   1584     const VkPresentRegionKHR* regions =
   1585         (present_regions) ? present_regions->pRegions : nullptr;
   1586     const VkPresentTimeGOOGLE* times =
   1587         (present_times) ? present_times->pTimes : nullptr;
   1588     const VkAllocationCallbacks* allocator = &GetData(device).allocator;
   1589     android_native_rect_t* rects = nullptr;
   1590     uint32_t nrects = 0;
   1591 
   1592     for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
   1593         Swapchain& swapchain =
   1594             *SwapchainFromHandle(present_info->pSwapchains[sc]);
   1595         uint32_t image_idx = present_info->pImageIndices[sc];
   1596         Swapchain::Image& img = swapchain.images[image_idx];
   1597         const VkPresentRegionKHR* region =
   1598             (regions && !swapchain.mailbox_mode) ? &regions[sc] : nullptr;
   1599         const VkPresentTimeGOOGLE* time = (times) ? &times[sc] : nullptr;
   1600         VkResult swapchain_result = VK_SUCCESS;
   1601         VkResult result;
   1602         int err;
   1603 
   1604         int fence = -1;
   1605         result = dispatch.QueueSignalReleaseImageANDROID(
   1606             queue, present_info->waitSemaphoreCount,
   1607             present_info->pWaitSemaphores, img.image, &fence);
   1608         if (result != VK_SUCCESS) {
   1609             ALOGE("QueueSignalReleaseImageANDROID failed: %d", result);
   1610             swapchain_result = result;
   1611         }
   1612 
   1613         if (swapchain.surface.swapchain_handle ==
   1614             present_info->pSwapchains[sc]) {
   1615             ANativeWindow* window = swapchain.surface.window.get();
   1616             if (swapchain_result == VK_SUCCESS) {
   1617                 if (region) {
   1618                     // Process the incremental-present hint for this swapchain:
   1619                     uint32_t rcount = region->rectangleCount;
   1620                     if (rcount > nrects) {
   1621                         android_native_rect_t* new_rects =
   1622                             static_cast<android_native_rect_t*>(
   1623                                 allocator->pfnReallocation(
   1624                                     allocator->pUserData, rects,
   1625                                     sizeof(android_native_rect_t) * rcount,
   1626                                     alignof(android_native_rect_t),
   1627                                     VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
   1628                         if (new_rects) {
   1629                             rects = new_rects;
   1630                             nrects = rcount;
   1631                         } else {
   1632                             rcount = 0;  // Ignore the hint for this swapchain
   1633                         }
   1634                     }
   1635                     for (uint32_t r = 0; r < rcount; ++r) {
   1636                         if (region->pRectangles[r].layer > 0) {
   1637                             ALOGV(
   1638                                 "vkQueuePresentKHR ignoring invalid layer "
   1639                                 "(%u); using layer 0 instead",
   1640                                 region->pRectangles[r].layer);
   1641                         }
   1642                         int x = region->pRectangles[r].offset.x;
   1643                         int y = region->pRectangles[r].offset.y;
   1644                         int width = static_cast<int>(
   1645                             region->pRectangles[r].extent.width);
   1646                         int height = static_cast<int>(
   1647                             region->pRectangles[r].extent.height);
   1648                         android_native_rect_t* cur_rect = &rects[r];
   1649                         cur_rect->left = x;
   1650                         cur_rect->top = y + height;
   1651                         cur_rect->right = x + width;
   1652                         cur_rect->bottom = y;
   1653                     }
   1654                     native_window_set_surface_damage(window, rects, rcount);
   1655                 }
   1656                 if (time) {
   1657                     if (!swapchain.frame_timestamps_enabled) {
   1658                         ALOGV(
   1659                             "Calling "
   1660                             "native_window_enable_frame_timestamps(true)");
   1661                         native_window_enable_frame_timestamps(window, true);
   1662                         swapchain.frame_timestamps_enabled = true;
   1663                     }
   1664 
   1665                     // Record the nativeFrameId so it can be later correlated to
   1666                     // this present.
   1667                     uint64_t nativeFrameId = 0;
   1668                     err = native_window_get_next_frame_id(
   1669                             window, &nativeFrameId);
   1670                     if (err != android::NO_ERROR) {
   1671                         ALOGE("Failed to get next native frame ID.");
   1672                     }
   1673 
   1674                     // Add a new timing record with the user's presentID and
   1675                     // the nativeFrameId.
   1676                     swapchain.timing.push_back(TimingInfo(time, nativeFrameId));
   1677                     while (swapchain.timing.size() > MAX_TIMING_INFOS) {
   1678                         swapchain.timing.removeAt(0);
   1679                     }
   1680                     if (time->desiredPresentTime) {
   1681                         // Set the desiredPresentTime:
   1682                         ALOGV(
   1683                             "Calling "
   1684                             "native_window_set_buffers_timestamp(%" PRId64 ")",
   1685                             time->desiredPresentTime);
   1686                         native_window_set_buffers_timestamp(
   1687                             window,
   1688                             static_cast<int64_t>(time->desiredPresentTime));
   1689                     }
   1690                 }
   1691 
   1692                 err = window->queueBuffer(window, img.buffer.get(), fence);
   1693                 // queueBuffer always closes fence, even on error
   1694                 if (err != 0) {
   1695                     // TODO(jessehall): What now? We should probably cancel the
   1696                     // buffer, I guess?
   1697                     ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
   1698                     swapchain_result = WorstPresentResult(
   1699                         swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
   1700                 }
   1701                 if (img.dequeue_fence >= 0) {
   1702                     close(img.dequeue_fence);
   1703                     img.dequeue_fence = -1;
   1704                 }
   1705                 img.dequeued = false;
   1706 
   1707                 // If the swapchain is in shared mode, immediately dequeue the
   1708                 // buffer so it can be presented again without an intervening
   1709                 // call to AcquireNextImageKHR. We expect to get the same buffer
   1710                 // back from every call to dequeueBuffer in this mode.
   1711                 if (swapchain.shared && swapchain_result == VK_SUCCESS) {
   1712                     ANativeWindowBuffer* buffer;
   1713                     int fence_fd;
   1714                     err = window->dequeueBuffer(window, &buffer, &fence_fd);
   1715                     if (err != 0) {
   1716                         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
   1717                         swapchain_result = WorstPresentResult(swapchain_result,
   1718                             VK_ERROR_SURFACE_LOST_KHR);
   1719                     }
   1720                     else if (img.buffer != buffer) {
   1721                         ALOGE("got wrong image back for shared swapchain");
   1722                         swapchain_result = WorstPresentResult(swapchain_result,
   1723                             VK_ERROR_SURFACE_LOST_KHR);
   1724                     }
   1725                     else {
   1726                         img.dequeue_fence = fence_fd;
   1727                         img.dequeued = true;
   1728                     }
   1729                 }
   1730             }
   1731             if (swapchain_result != VK_SUCCESS) {
   1732                 ReleaseSwapchainImage(device, window, fence, img);
   1733                 OrphanSwapchain(device, &swapchain);
   1734             }
   1735             int window_transform_hint;
   1736             err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
   1737                                 &window_transform_hint);
   1738             if (err != 0) {
   1739                 ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
   1740                       strerror(-err), err);
   1741                 swapchain_result = WorstPresentResult(
   1742                     swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
   1743             }
   1744             if (swapchain.pre_transform != window_transform_hint) {
   1745                 swapchain_result =
   1746                     WorstPresentResult(swapchain_result, VK_SUBOPTIMAL_KHR);
   1747             }
   1748         } else {
   1749             ReleaseSwapchainImage(device, nullptr, fence, img);
   1750             swapchain_result = VK_ERROR_OUT_OF_DATE_KHR;
   1751         }
   1752 
   1753         if (present_info->pResults)
   1754             present_info->pResults[sc] = swapchain_result;
   1755 
   1756         if (swapchain_result != final_result)
   1757             final_result = WorstPresentResult(final_result, swapchain_result);
   1758     }
   1759     if (rects) {
   1760         allocator->pfnFree(allocator->pUserData, rects);
   1761     }
   1762 
   1763     return final_result;
   1764 }
   1765 
   1766 VKAPI_ATTR
   1767 VkResult GetRefreshCycleDurationGOOGLE(
   1768     VkDevice,
   1769     VkSwapchainKHR swapchain_handle,
   1770     VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
   1771     ATRACE_CALL();
   1772 
   1773     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
   1774     VkResult result = VK_SUCCESS;
   1775 
   1776     pDisplayTimingProperties->refreshDuration = swapchain.get_refresh_duration();
   1777 
   1778     return result;
   1779 }
   1780 
   1781 VKAPI_ATTR
   1782 VkResult GetPastPresentationTimingGOOGLE(
   1783     VkDevice,
   1784     VkSwapchainKHR swapchain_handle,
   1785     uint32_t* count,
   1786     VkPastPresentationTimingGOOGLE* timings) {
   1787     ATRACE_CALL();
   1788 
   1789     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
   1790     ANativeWindow* window = swapchain.surface.window.get();
   1791     VkResult result = VK_SUCCESS;
   1792 
   1793     if (!swapchain.frame_timestamps_enabled) {
   1794         ALOGV("Calling native_window_enable_frame_timestamps(true)");
   1795         native_window_enable_frame_timestamps(window, true);
   1796         swapchain.frame_timestamps_enabled = true;
   1797     }
   1798 
   1799     if (timings) {
   1800         // TODO(ianelliott): plumb return value (e.g. VK_INCOMPLETE)
   1801         copy_ready_timings(swapchain, count, timings);
   1802     } else {
   1803         *count = get_num_ready_timings(swapchain);
   1804     }
   1805 
   1806     return result;
   1807 }
   1808 
   1809 VKAPI_ATTR
   1810 VkResult GetSwapchainStatusKHR(
   1811     VkDevice,
   1812     VkSwapchainKHR swapchain_handle) {
   1813     ATRACE_CALL();
   1814 
   1815     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
   1816     VkResult result = VK_SUCCESS;
   1817 
   1818     if (swapchain.surface.swapchain_handle != swapchain_handle) {
   1819         return VK_ERROR_OUT_OF_DATE_KHR;
   1820     }
   1821 
   1822     // TODO(chrisforbes): Implement this function properly
   1823 
   1824     return result;
   1825 }
   1826 
   1827 VKAPI_ATTR void SetHdrMetadataEXT(
   1828     VkDevice,
   1829     uint32_t swapchainCount,
   1830     const VkSwapchainKHR* pSwapchains,
   1831     const VkHdrMetadataEXT* pHdrMetadataEXTs) {
   1832     ATRACE_CALL();
   1833 
   1834     for (uint32_t idx = 0; idx < swapchainCount; idx++) {
   1835         Swapchain* swapchain = SwapchainFromHandle(pSwapchains[idx]);
   1836         if (!swapchain)
   1837             continue;
   1838 
   1839         if (swapchain->surface.swapchain_handle != pSwapchains[idx]) continue;
   1840 
   1841         ANativeWindow* window = swapchain->surface.window.get();
   1842 
   1843         VkHdrMetadataEXT vulkanMetadata = pHdrMetadataEXTs[idx];
   1844         const android_smpte2086_metadata smpteMetdata = {
   1845             {vulkanMetadata.displayPrimaryRed.x,
   1846              vulkanMetadata.displayPrimaryRed.y},
   1847             {vulkanMetadata.displayPrimaryGreen.x,
   1848              vulkanMetadata.displayPrimaryGreen.y},
   1849             {vulkanMetadata.displayPrimaryBlue.x,
   1850              vulkanMetadata.displayPrimaryBlue.y},
   1851             {vulkanMetadata.whitePoint.x, vulkanMetadata.whitePoint.y},
   1852             vulkanMetadata.maxLuminance,
   1853             vulkanMetadata.minLuminance};
   1854         native_window_set_buffers_smpte2086_metadata(window, &smpteMetdata);
   1855 
   1856         const android_cta861_3_metadata cta8613Metadata = {
   1857             vulkanMetadata.maxContentLightLevel,
   1858             vulkanMetadata.maxFrameAverageLightLevel};
   1859         native_window_set_buffers_cta861_3_metadata(window, &cta8613Metadata);
   1860     }
   1861 
   1862     return;
   1863 }
   1864 
   1865 static void InterceptBindImageMemory2(
   1866     uint32_t bind_info_count,
   1867     const VkBindImageMemoryInfo* bind_infos,
   1868     std::vector<VkNativeBufferANDROID>* out_native_buffers,
   1869     std::vector<VkBindImageMemoryInfo>* out_bind_infos) {
   1870     out_native_buffers->clear();
   1871     out_bind_infos->clear();
   1872 
   1873     if (!bind_info_count)
   1874         return;
   1875 
   1876     std::unordered_set<uint32_t> intercepted_indexes;
   1877 
   1878     for (uint32_t idx = 0; idx < bind_info_count; idx++) {
   1879         auto info = reinterpret_cast<const VkBindImageMemorySwapchainInfoKHR*>(
   1880             bind_infos[idx].pNext);
   1881         while (info &&
   1882                info->sType !=
   1883                    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR) {
   1884             info = reinterpret_cast<const VkBindImageMemorySwapchainInfoKHR*>(
   1885                 info->pNext);
   1886         }
   1887 
   1888         if (!info)
   1889             continue;
   1890 
   1891         ALOG_ASSERT(info->swapchain != VK_NULL_HANDLE,
   1892                     "swapchain handle must not be NULL");
   1893         const Swapchain* swapchain = SwapchainFromHandle(info->swapchain);
   1894         ALOG_ASSERT(
   1895             info->imageIndex < swapchain->num_images,
   1896             "imageIndex must be less than the number of images in swapchain");
   1897 
   1898         ANativeWindowBuffer* buffer =
   1899             swapchain->images[info->imageIndex].buffer.get();
   1900         VkNativeBufferANDROID native_buffer = {
   1901 #pragma clang diagnostic push
   1902 #pragma clang diagnostic ignored "-Wold-style-cast"
   1903             .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
   1904 #pragma clang diagnostic pop
   1905             .pNext = bind_infos[idx].pNext,
   1906             .handle = buffer->handle,
   1907             .stride = buffer->stride,
   1908             .format = buffer->format,
   1909             .usage = int(buffer->usage),
   1910         };
   1911         // Reserve enough space to avoid letting re-allocation invalidate the
   1912         // addresses of the elements inside.
   1913         out_native_buffers->reserve(bind_info_count);
   1914         out_native_buffers->emplace_back(native_buffer);
   1915 
   1916         // Reserve the space now since we know how much is needed now.
   1917         out_bind_infos->reserve(bind_info_count);
   1918         out_bind_infos->emplace_back(bind_infos[idx]);
   1919         out_bind_infos->back().pNext = &out_native_buffers->back();
   1920 
   1921         intercepted_indexes.insert(idx);
   1922     }
   1923 
   1924     if (intercepted_indexes.empty())
   1925         return;
   1926 
   1927     for (uint32_t idx = 0; idx < bind_info_count; idx++) {
   1928         if (intercepted_indexes.count(idx))
   1929             continue;
   1930         out_bind_infos->emplace_back(bind_infos[idx]);
   1931     }
   1932 }
   1933 
   1934 VKAPI_ATTR
   1935 VkResult BindImageMemory2(VkDevice device,
   1936                           uint32_t bindInfoCount,
   1937                           const VkBindImageMemoryInfo* pBindInfos) {
   1938     ATRACE_CALL();
   1939 
   1940     // out_native_buffers is for maintaining the lifecycle of the constructed
   1941     // VkNativeBufferANDROID objects inside InterceptBindImageMemory2.
   1942     std::vector<VkNativeBufferANDROID> out_native_buffers;
   1943     std::vector<VkBindImageMemoryInfo> out_bind_infos;
   1944     InterceptBindImageMemory2(bindInfoCount, pBindInfos, &out_native_buffers,
   1945                               &out_bind_infos);
   1946     return GetData(device).driver.BindImageMemory2(
   1947         device, bindInfoCount,
   1948         out_bind_infos.empty() ? pBindInfos : out_bind_infos.data());
   1949 }
   1950 
   1951 VKAPI_ATTR
   1952 VkResult BindImageMemory2KHR(VkDevice device,
   1953                              uint32_t bindInfoCount,
   1954                              const VkBindImageMemoryInfo* pBindInfos) {
   1955     ATRACE_CALL();
   1956 
   1957     std::vector<VkNativeBufferANDROID> out_native_buffers;
   1958     std::vector<VkBindImageMemoryInfo> out_bind_infos;
   1959     InterceptBindImageMemory2(bindInfoCount, pBindInfos, &out_native_buffers,
   1960                               &out_bind_infos);
   1961     return GetData(device).driver.BindImageMemory2KHR(
   1962         device, bindInfoCount,
   1963         out_bind_infos.empty() ? pBindInfos : out_bind_infos.data());
   1964 }
   1965 
   1966 }  // namespace driver
   1967 }  // namespace vulkan
   1968