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