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 
TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform)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 
TranslateNativeToVulkanTransform(int native)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 
InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform)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;
TimingInfo(const VkPresentTimeGOOGLE * qp,uint64_t nativeFrameId)138     TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId)
139         : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
140           native_frame_id_(nativeFrameId) {}
ready() const141     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     }
calculate(int64_t rdur)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     }
get_values(VkPastPresentationTimingGOOGLE * values) const189     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 
HandleFromSurface(Surface * surface)212 VkSurfaceKHR HandleFromSurface(Surface* surface) {
213     return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface));
214 }
215 
SurfaceFromHandle(VkSurfaceKHR handle)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 {
Swapchainvulkan::driver::__anon3017a7eb0111::Swapchain227     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     }
get_refresh_durationvulkan::driver::__anon3017a7eb0111::Swapchain243     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 {
Imagevulkan::driver::__anon3017a7eb0111::Swapchain::Image262         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 
HandleFromSwapchain(Swapchain * swapchain)276 VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
277     return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain));
278 }
279 
SwapchainFromHandle(VkSwapchainKHR handle)280 Swapchain* SwapchainFromHandle(VkSwapchainKHR handle) {
281     return reinterpret_cast<Swapchain*>(handle);
282 }
283 
ReleaseSwapchainImage(VkDevice device,ANativeWindow * window,int release_fence,Swapchain::Image & image)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 
OrphanSwapchain(VkDevice device,Swapchain * swapchain)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 
get_num_ready_timings(Swapchain & swapchain)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)!!!
copy_ready_timings(Swapchain & swapchain,uint32_t * count,VkPastPresentationTimingGOOGLE * timings)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 
GetNativePixelFormat(VkFormat format)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 
GetNativeDataspace(VkColorSpaceKHR colorspace)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
CreateAndroidSurfaceKHR(VkInstance instance,const VkAndroidSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * allocator,VkSurfaceKHR * out_surface)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
DestroySurfaceKHR(VkInstance instance,VkSurfaceKHR surface_handle,const VkAllocationCallbacks * allocator)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
GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice,uint32_t,VkSurfaceKHR surface_handle,VkBool32 * supported)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
GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice,VkSurfaceKHR surface,VkSurfaceCapabilitiesKHR * capabilities)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
GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev,VkSurfaceKHR surface_handle,uint32_t * count,VkSurfaceFormatKHR * formats)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     bool wide_color_support = false;
712     Surface& surface = *SurfaceFromHandle(surface_handle);
713     int err = native_window_get_wide_color_support(surface.window.get(),
714                                                    &wide_color_support);
715     if (err) {
716         // Not allowed to return a more sensible error code, so do this
717         return VK_ERROR_OUT_OF_HOST_MEMORY;
718     }
719     ALOGV("wide_color_support is: %d", wide_color_support);
720     wide_color_support =
721         wide_color_support &&
722         instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
723 
724     AHardwareBuffer_Desc desc = {};
725     desc.width = 1;
726     desc.height = 1;
727     desc.layers = 1;
728     desc.usage = surface.consumer_usage |
729                  AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
730                  AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
731 
732     // We must support R8G8B8A8
733     std::vector<VkSurfaceFormatKHR> all_formats = {
734         {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
735         {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
736 
737     if (wide_color_support) {
738         all_formats.emplace_back(VkSurfaceFormatKHR{
739             VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
740         all_formats.emplace_back(VkSurfaceFormatKHR{
741             VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
742     }
743 
744     desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
745     if (AHardwareBuffer_isSupported(&desc)) {
746         all_formats.emplace_back(VkSurfaceFormatKHR{
747             VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
748     }
749 
750     desc.format = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
751     if (AHardwareBuffer_isSupported(&desc)) {
752         all_formats.emplace_back(VkSurfaceFormatKHR{
753             VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
754         if (wide_color_support) {
755             all_formats.emplace_back(
756                 VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
757                                    VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT});
758             all_formats.emplace_back(
759                 VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
760                                    VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT});
761         }
762     }
763 
764     desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
765     if (AHardwareBuffer_isSupported(&desc)) {
766         all_formats.emplace_back(
767             VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
768                                VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
769         if (wide_color_support) {
770             all_formats.emplace_back(
771                 VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
772                                    VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
773         }
774     }
775 
776     VkResult result = VK_SUCCESS;
777     if (formats) {
778         uint32_t transfer_count = all_formats.size();
779         if (transfer_count > *count) {
780             transfer_count = *count;
781             result = VK_INCOMPLETE;
782         }
783         std::copy(all_formats.begin(), all_formats.begin() + transfer_count,
784                   formats);
785         *count = transfer_count;
786     } else {
787         *count = all_formats.size();
788     }
789 
790     return result;
791 }
792 
793 VKAPI_ATTR
GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,VkSurfaceCapabilities2KHR * pSurfaceCapabilities)794 VkResult GetPhysicalDeviceSurfaceCapabilities2KHR(
795     VkPhysicalDevice physicalDevice,
796     const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
797     VkSurfaceCapabilities2KHR* pSurfaceCapabilities) {
798     ATRACE_CALL();
799 
800     VkResult result = GetPhysicalDeviceSurfaceCapabilitiesKHR(
801         physicalDevice, pSurfaceInfo->surface,
802         &pSurfaceCapabilities->surfaceCapabilities);
803 
804     VkSurfaceCapabilities2KHR* caps = pSurfaceCapabilities;
805     while (caps->pNext) {
806         caps = reinterpret_cast<VkSurfaceCapabilities2KHR*>(caps->pNext);
807 
808         switch (caps->sType) {
809             case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: {
810                 VkSharedPresentSurfaceCapabilitiesKHR* shared_caps =
811                     reinterpret_cast<VkSharedPresentSurfaceCapabilitiesKHR*>(
812                         caps);
813                 // Claim same set of usage flags are supported for
814                 // shared present modes as for other modes.
815                 shared_caps->sharedPresentSupportedUsageFlags =
816                     pSurfaceCapabilities->surfaceCapabilities
817                         .supportedUsageFlags;
818             } break;
819 
820             default:
821                 // Ignore all other extension structs
822                 break;
823         }
824     }
825 
826     return result;
827 }
828 
829 VKAPI_ATTR
GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,uint32_t * pSurfaceFormatCount,VkSurfaceFormat2KHR * pSurfaceFormats)830 VkResult GetPhysicalDeviceSurfaceFormats2KHR(
831     VkPhysicalDevice physicalDevice,
832     const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
833     uint32_t* pSurfaceFormatCount,
834     VkSurfaceFormat2KHR* pSurfaceFormats) {
835     ATRACE_CALL();
836 
837     if (!pSurfaceFormats) {
838         return GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice,
839                                                   pSurfaceInfo->surface,
840                                                   pSurfaceFormatCount, nullptr);
841     } else {
842         // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
843         // after the call.
844         android::Vector<VkSurfaceFormatKHR> surface_formats;
845         surface_formats.resize(*pSurfaceFormatCount);
846         VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
847             physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
848             &surface_formats.editItemAt(0));
849 
850         if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
851             // marshal results individually due to stride difference.
852             // completely ignore any chained extension structs.
853             uint32_t formats_to_marshal = *pSurfaceFormatCount;
854             for (uint32_t i = 0u; i < formats_to_marshal; i++) {
855                 pSurfaceFormats[i].surfaceFormat = surface_formats[i];
856             }
857         }
858 
859         return result;
860     }
861 }
862 
863 VKAPI_ATTR
GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev,VkSurfaceKHR surface,uint32_t * count,VkPresentModeKHR * modes)864 VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev,
865                                                  VkSurfaceKHR surface,
866                                                  uint32_t* count,
867                                                  VkPresentModeKHR* modes) {
868     ATRACE_CALL();
869 
870     int err;
871     int query_value;
872     ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
873 
874     err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
875     if (err != 0 || query_value < 0) {
876         ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) value=%d",
877               strerror(-err), err, query_value);
878         return VK_ERROR_SURFACE_LOST_KHR;
879     }
880     uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
881 
882     err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
883     if (err != 0 || query_value < 0) {
884         ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d",
885               strerror(-err), err, query_value);
886         return VK_ERROR_SURFACE_LOST_KHR;
887     }
888     uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
889 
890     android::Vector<VkPresentModeKHR> present_modes;
891     if (min_undequeued_buffers + 1 < max_buffer_count)
892         present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
893     present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
894 
895     VkPhysicalDevicePresentationPropertiesANDROID present_properties;
896     if (QueryPresentationProperties(pdev, &present_properties)) {
897         if (present_properties.sharedImage) {
898             present_modes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR);
899             present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
900         }
901     }
902 
903     uint32_t num_modes = uint32_t(present_modes.size());
904 
905     VkResult result = VK_SUCCESS;
906     if (modes) {
907         if (*count < num_modes)
908             result = VK_INCOMPLETE;
909         *count = std::min(*count, num_modes);
910         std::copy(present_modes.begin(), present_modes.begin() + int(*count), modes);
911     } else {
912         *count = num_modes;
913     }
914     return result;
915 }
916 
917 VKAPI_ATTR
GetDeviceGroupPresentCapabilitiesKHR(VkDevice,VkDeviceGroupPresentCapabilitiesKHR * pDeviceGroupPresentCapabilities)918 VkResult GetDeviceGroupPresentCapabilitiesKHR(
919     VkDevice,
920     VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
921     ATRACE_CALL();
922 
923     ALOGV_IF(pDeviceGroupPresentCapabilities->sType !=
924                  VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR,
925              "vkGetDeviceGroupPresentCapabilitiesKHR: invalid "
926              "VkDeviceGroupPresentCapabilitiesKHR structure type %d",
927              pDeviceGroupPresentCapabilities->sType);
928 
929     memset(pDeviceGroupPresentCapabilities->presentMask, 0,
930            sizeof(pDeviceGroupPresentCapabilities->presentMask));
931 
932     // assume device group of size 1
933     pDeviceGroupPresentCapabilities->presentMask[0] = 1 << 0;
934     pDeviceGroupPresentCapabilities->modes =
935         VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
936 
937     return VK_SUCCESS;
938 }
939 
940 VKAPI_ATTR
GetDeviceGroupSurfacePresentModesKHR(VkDevice,VkSurfaceKHR,VkDeviceGroupPresentModeFlagsKHR * pModes)941 VkResult GetDeviceGroupSurfacePresentModesKHR(
942     VkDevice,
943     VkSurfaceKHR,
944     VkDeviceGroupPresentModeFlagsKHR* pModes) {
945     ATRACE_CALL();
946 
947     *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
948     return VK_SUCCESS;
949 }
950 
951 VKAPI_ATTR
GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice,VkSurfaceKHR surface,uint32_t * pRectCount,VkRect2D * pRects)952 VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice,
953                                                VkSurfaceKHR surface,
954                                                uint32_t* pRectCount,
955                                                VkRect2D* pRects) {
956     ATRACE_CALL();
957 
958     if (!pRects) {
959         *pRectCount = 1;
960     } else {
961         uint32_t count = std::min(*pRectCount, 1u);
962         bool incomplete = *pRectCount < 1;
963 
964         *pRectCount = count;
965 
966         if (incomplete) {
967             return VK_INCOMPLETE;
968         }
969 
970         int err;
971         ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
972 
973         int width = 0, height = 0;
974         err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
975         if (err != 0) {
976             ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
977                   strerror(-err), err);
978         }
979         err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
980         if (err != 0) {
981             ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
982                   strerror(-err), err);
983         }
984 
985         // TODO: Return something better than "whole window"
986         pRects[0].offset.x = 0;
987         pRects[0].offset.y = 0;
988         pRects[0].extent = VkExtent2D{static_cast<uint32_t>(width),
989                                       static_cast<uint32_t>(height)};
990     }
991     return VK_SUCCESS;
992 }
993 
994 VKAPI_ATTR
CreateSwapchainKHR(VkDevice device,const VkSwapchainCreateInfoKHR * create_info,const VkAllocationCallbacks * allocator,VkSwapchainKHR * swapchain_handle)995 VkResult CreateSwapchainKHR(VkDevice device,
996                             const VkSwapchainCreateInfoKHR* create_info,
997                             const VkAllocationCallbacks* allocator,
998                             VkSwapchainKHR* swapchain_handle) {
999     ATRACE_CALL();
1000 
1001     int err;
1002     VkResult result = VK_SUCCESS;
1003 
1004     ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
1005           " minImageCount=%u imageFormat=%u imageColorSpace=%u"
1006           " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
1007           " oldSwapchain=0x%" PRIx64,
1008           reinterpret_cast<uint64_t>(create_info->surface),
1009           create_info->minImageCount, create_info->imageFormat,
1010           create_info->imageColorSpace, create_info->imageExtent.width,
1011           create_info->imageExtent.height, create_info->imageUsage,
1012           create_info->preTransform, create_info->presentMode,
1013           reinterpret_cast<uint64_t>(create_info->oldSwapchain));
1014 
1015     if (!allocator)
1016         allocator = &GetData(device).allocator;
1017 
1018     android_pixel_format native_pixel_format =
1019         GetNativePixelFormat(create_info->imageFormat);
1020     android_dataspace native_dataspace =
1021         GetNativeDataspace(create_info->imageColorSpace);
1022     if (native_dataspace == HAL_DATASPACE_UNKNOWN) {
1023         ALOGE(
1024             "CreateSwapchainKHR(VkSwapchainCreateInfoKHR.imageColorSpace = %d) "
1025             "failed: Unsupported color space",
1026             create_info->imageColorSpace);
1027         return VK_ERROR_INITIALIZATION_FAILED;
1028     }
1029 
1030     ALOGV_IF(create_info->imageArrayLayers != 1,
1031              "swapchain imageArrayLayers=%u not supported",
1032              create_info->imageArrayLayers);
1033     ALOGV_IF((create_info->preTransform & ~kSupportedTransforms) != 0,
1034              "swapchain preTransform=%#x not supported",
1035              create_info->preTransform);
1036     ALOGV_IF(!(create_info->presentMode == VK_PRESENT_MODE_FIFO_KHR ||
1037                create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ||
1038                create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
1039                create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR),
1040              "swapchain presentMode=%u not supported",
1041              create_info->presentMode);
1042 
1043     Surface& surface = *SurfaceFromHandle(create_info->surface);
1044 
1045     if (surface.swapchain_handle != create_info->oldSwapchain) {
1046         ALOGV("Can't create a swapchain for VkSurfaceKHR 0x%" PRIx64
1047               " because it already has active swapchain 0x%" PRIx64
1048               " but VkSwapchainCreateInfo::oldSwapchain=0x%" PRIx64,
1049               reinterpret_cast<uint64_t>(create_info->surface),
1050               reinterpret_cast<uint64_t>(surface.swapchain_handle),
1051               reinterpret_cast<uint64_t>(create_info->oldSwapchain));
1052         return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
1053     }
1054     if (create_info->oldSwapchain != VK_NULL_HANDLE)
1055         OrphanSwapchain(device, SwapchainFromHandle(create_info->oldSwapchain));
1056 
1057     // -- Reset the native window --
1058     // The native window might have been used previously, and had its properties
1059     // changed from defaults. That will affect the answer we get for queries
1060     // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we
1061     // attempt such queries.
1062 
1063     // The native window only allows dequeueing all buffers before any have
1064     // been queued, since after that point at least one is assumed to be in
1065     // non-FREE state at any given time. Disconnecting and re-connecting
1066     // orphans the previous buffers, getting us back to the state where we can
1067     // dequeue all buffers.
1068     err = native_window_api_disconnect(surface.window.get(),
1069                                        NATIVE_WINDOW_API_EGL);
1070     ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)",
1071              strerror(-err), err);
1072     err =
1073         native_window_api_connect(surface.window.get(), NATIVE_WINDOW_API_EGL);
1074     ALOGW_IF(err != 0, "native_window_api_connect failed: %s (%d)",
1075              strerror(-err), err);
1076 
1077     err = native_window_set_buffer_count(surface.window.get(), 0);
1078     if (err != 0) {
1079         ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
1080               strerror(-err), err);
1081         return VK_ERROR_SURFACE_LOST_KHR;
1082     }
1083 
1084     int swap_interval =
1085         create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
1086     err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
1087     if (err != 0) {
1088         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1089         // errors and translate them to valid Vulkan result codes?
1090         ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
1091               strerror(-err), err);
1092         return VK_ERROR_SURFACE_LOST_KHR;
1093     }
1094 
1095     err = native_window_set_shared_buffer_mode(surface.window.get(), false);
1096     if (err != 0) {
1097         ALOGE("native_window_set_shared_buffer_mode(false) failed: %s (%d)",
1098               strerror(-err), err);
1099         return VK_ERROR_SURFACE_LOST_KHR;
1100     }
1101 
1102     err = native_window_set_auto_refresh(surface.window.get(), false);
1103     if (err != 0) {
1104         ALOGE("native_window_set_auto_refresh(false) failed: %s (%d)",
1105               strerror(-err), err);
1106         return VK_ERROR_SURFACE_LOST_KHR;
1107     }
1108 
1109     // -- Configure the native window --
1110 
1111     const auto& dispatch = GetData(device).driver;
1112 
1113     err = native_window_set_buffers_format(surface.window.get(),
1114                                            native_pixel_format);
1115     if (err != 0) {
1116         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1117         // errors and translate them to valid Vulkan result codes?
1118         ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
1119               native_pixel_format, strerror(-err), err);
1120         return VK_ERROR_SURFACE_LOST_KHR;
1121     }
1122     err = native_window_set_buffers_data_space(surface.window.get(),
1123                                                native_dataspace);
1124     if (err != 0) {
1125         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1126         // errors and translate them to valid Vulkan result codes?
1127         ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
1128               native_dataspace, strerror(-err), err);
1129         return VK_ERROR_SURFACE_LOST_KHR;
1130     }
1131 
1132     err = native_window_set_buffers_dimensions(
1133         surface.window.get(), static_cast<int>(create_info->imageExtent.width),
1134         static_cast<int>(create_info->imageExtent.height));
1135     if (err != 0) {
1136         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1137         // errors and translate them to valid Vulkan result codes?
1138         ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
1139               create_info->imageExtent.width, create_info->imageExtent.height,
1140               strerror(-err), err);
1141         return VK_ERROR_SURFACE_LOST_KHR;
1142     }
1143 
1144     // VkSwapchainCreateInfo::preTransform indicates the transformation the app
1145     // applied during rendering. native_window_set_transform() expects the
1146     // inverse: the transform the app is requesting that the compositor perform
1147     // during composition. With native windows, pre-transform works by rendering
1148     // with the same transform the compositor is applying (as in Vulkan), but
1149     // then requesting the inverse transform, so that when the compositor does
1150     // it's job the two transforms cancel each other out and the compositor ends
1151     // up applying an identity transform to the app's buffer.
1152     err = native_window_set_buffers_transform(
1153         surface.window.get(),
1154         InvertTransformToNative(create_info->preTransform));
1155     if (err != 0) {
1156         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1157         // errors and translate them to valid Vulkan result codes?
1158         ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
1159               InvertTransformToNative(create_info->preTransform),
1160               strerror(-err), err);
1161         return VK_ERROR_SURFACE_LOST_KHR;
1162     }
1163 
1164     err = native_window_set_scaling_mode(
1165         surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
1166     if (err != 0) {
1167         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1168         // errors and translate them to valid Vulkan result codes?
1169         ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
1170               strerror(-err), err);
1171         return VK_ERROR_SURFACE_LOST_KHR;
1172     }
1173 
1174     VkSwapchainImageUsageFlagsANDROID swapchain_image_usage = 0;
1175     if (create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
1176         create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
1177         swapchain_image_usage |= VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID;
1178         err = native_window_set_shared_buffer_mode(surface.window.get(), true);
1179         if (err != 0) {
1180             ALOGE("native_window_set_shared_buffer_mode failed: %s (%d)", strerror(-err), err);
1181             return VK_ERROR_SURFACE_LOST_KHR;
1182         }
1183     }
1184 
1185     if (create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
1186         err = native_window_set_auto_refresh(surface.window.get(), true);
1187         if (err != 0) {
1188             ALOGE("native_window_set_auto_refresh failed: %s (%d)", strerror(-err), err);
1189             return VK_ERROR_SURFACE_LOST_KHR;
1190         }
1191     }
1192 
1193     int query_value;
1194     err = surface.window->query(surface.window.get(),
1195                                 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1196                                 &query_value);
1197     if (err != 0 || query_value < 0) {
1198         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1199         // errors and translate them to valid Vulkan result codes?
1200         ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
1201               query_value);
1202         return VK_ERROR_SURFACE_LOST_KHR;
1203     }
1204     uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
1205     uint32_t num_images =
1206         (swap_interval ? create_info->minImageCount
1207                        : std::max(3u, create_info->minImageCount)) -
1208         1 + min_undequeued_buffers;
1209 
1210     // Lower layer insists that we have at least two buffers. This is wasteful
1211     // and we'd like to relax it in the shared case, but not all the pieces are
1212     // in place for that to work yet. Note we only lie to the lower layer-- we
1213     // don't want to give the app back a swapchain with extra images (which they
1214     // can't actually use!).
1215     err = native_window_set_buffer_count(surface.window.get(), std::max(2u, num_images));
1216     if (err != 0) {
1217         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1218         // errors and translate them to valid Vulkan result codes?
1219         ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
1220               strerror(-err), err);
1221         return VK_ERROR_SURFACE_LOST_KHR;
1222     }
1223 
1224     int32_t legacy_usage = 0;
1225     if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
1226         uint64_t consumer_usage, producer_usage;
1227         ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsage2ANDROID");
1228         result = dispatch.GetSwapchainGrallocUsage2ANDROID(
1229             device, create_info->imageFormat, create_info->imageUsage,
1230             swapchain_image_usage, &consumer_usage, &producer_usage);
1231         ATRACE_END();
1232         if (result != VK_SUCCESS) {
1233             ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
1234             return VK_ERROR_SURFACE_LOST_KHR;
1235         }
1236         legacy_usage =
1237             android_convertGralloc1To0Usage(producer_usage, consumer_usage);
1238     } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
1239         ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsageANDROID");
1240         result = dispatch.GetSwapchainGrallocUsageANDROID(
1241             device, create_info->imageFormat, create_info->imageUsage,
1242             &legacy_usage);
1243         ATRACE_END();
1244         if (result != VK_SUCCESS) {
1245             ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
1246             return VK_ERROR_SURFACE_LOST_KHR;
1247         }
1248     }
1249     uint64_t native_usage = static_cast<uint64_t>(legacy_usage);
1250 
1251     bool createProtectedSwapchain = false;
1252     if (create_info->flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR) {
1253         createProtectedSwapchain = true;
1254         native_usage |= BufferUsage::PROTECTED;
1255     }
1256     err = native_window_set_usage(surface.window.get(), native_usage);
1257     if (err != 0) {
1258         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1259         // errors and translate them to valid Vulkan result codes?
1260         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
1261         return VK_ERROR_SURFACE_LOST_KHR;
1262     }
1263 
1264     // -- Allocate our Swapchain object --
1265     // After this point, we must deallocate the swapchain on error.
1266 
1267     void* mem = allocator->pfnAllocation(allocator->pUserData,
1268                                          sizeof(Swapchain), alignof(Swapchain),
1269                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1270     if (!mem)
1271         return VK_ERROR_OUT_OF_HOST_MEMORY;
1272     Swapchain* swapchain = new (mem)
1273         Swapchain(surface, num_images, create_info->presentMode,
1274                   TranslateVulkanToNativeTransform(create_info->preTransform));
1275     // -- Dequeue all buffers and create a VkImage for each --
1276     // Any failures during or after this must cancel the dequeued buffers.
1277 
1278     VkSwapchainImageCreateInfoANDROID swapchain_image_create = {
1279 #pragma clang diagnostic push
1280 #pragma clang diagnostic ignored "-Wold-style-cast"
1281         .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID,
1282 #pragma clang diagnostic pop
1283         .pNext = nullptr,
1284         .usage = swapchain_image_usage,
1285     };
1286     VkNativeBufferANDROID image_native_buffer = {
1287 #pragma clang diagnostic push
1288 #pragma clang diagnostic ignored "-Wold-style-cast"
1289         .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
1290 #pragma clang diagnostic pop
1291         .pNext = &swapchain_image_create,
1292     };
1293     VkImageCreateInfo image_create = {
1294         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1295         .pNext = &image_native_buffer,
1296         .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
1297         .imageType = VK_IMAGE_TYPE_2D,
1298         .format = create_info->imageFormat,
1299         .extent = {0, 0, 1},
1300         .mipLevels = 1,
1301         .arrayLayers = 1,
1302         .samples = VK_SAMPLE_COUNT_1_BIT,
1303         .tiling = VK_IMAGE_TILING_OPTIMAL,
1304         .usage = create_info->imageUsage,
1305         .sharingMode = create_info->imageSharingMode,
1306         .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
1307         .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
1308     };
1309 
1310     for (uint32_t i = 0; i < num_images; i++) {
1311         Swapchain::Image& img = swapchain->images[i];
1312 
1313         ANativeWindowBuffer* buffer;
1314         err = surface.window->dequeueBuffer(surface.window.get(), &buffer,
1315                                             &img.dequeue_fence);
1316         if (err != 0) {
1317             // TODO(jessehall): Improve error reporting. Can we enumerate
1318             // possible errors and translate them to valid Vulkan result codes?
1319             ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
1320             switch (-err) {
1321                 case ENOMEM:
1322                     result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
1323                     break;
1324                 default:
1325                     result = VK_ERROR_SURFACE_LOST_KHR;
1326                     break;
1327             }
1328             break;
1329         }
1330         img.buffer = buffer;
1331         img.dequeued = true;
1332 
1333         image_create.extent =
1334             VkExtent3D{static_cast<uint32_t>(img.buffer->width),
1335                        static_cast<uint32_t>(img.buffer->height),
1336                        1};
1337         image_native_buffer.handle = img.buffer->handle;
1338         image_native_buffer.stride = img.buffer->stride;
1339         image_native_buffer.format = img.buffer->format;
1340         image_native_buffer.usage = int(img.buffer->usage);
1341         android_convertGralloc0To1Usage(int(img.buffer->usage),
1342             &image_native_buffer.usage2.producer,
1343             &image_native_buffer.usage2.consumer);
1344 
1345         ATRACE_BEGIN("dispatch.CreateImage");
1346         result =
1347             dispatch.CreateImage(device, &image_create, nullptr, &img.image);
1348         ATRACE_END();
1349         if (result != VK_SUCCESS) {
1350             ALOGD("vkCreateImage w/ native buffer failed: %u", result);
1351             break;
1352         }
1353     }
1354 
1355     // -- Cancel all buffers, returning them to the queue --
1356     // If an error occurred before, also destroy the VkImage and release the
1357     // buffer reference. Otherwise, we retain a strong reference to the buffer.
1358     //
1359     // TODO(jessehall): The error path here is the same as DestroySwapchain,
1360     // but not the non-error path. Should refactor/unify.
1361     for (uint32_t i = 0; i < num_images; i++) {
1362         Swapchain::Image& img = swapchain->images[i];
1363         if (img.dequeued) {
1364             if (!swapchain->shared) {
1365                 surface.window->cancelBuffer(surface.window.get(), img.buffer.get(),
1366                                              img.dequeue_fence);
1367                 img.dequeue_fence = -1;
1368                 img.dequeued = false;
1369             }
1370         }
1371         if (result != VK_SUCCESS) {
1372             if (img.image) {
1373                 ATRACE_BEGIN("dispatch.DestroyImage");
1374                 dispatch.DestroyImage(device, img.image, nullptr);
1375                 ATRACE_END();
1376             }
1377         }
1378     }
1379 
1380     if (result != VK_SUCCESS) {
1381         swapchain->~Swapchain();
1382         allocator->pfnFree(allocator->pUserData, swapchain);
1383         return result;
1384     }
1385 
1386     surface.swapchain_handle = HandleFromSwapchain(swapchain);
1387     *swapchain_handle = surface.swapchain_handle;
1388     return VK_SUCCESS;
1389 }
1390 
1391 VKAPI_ATTR
DestroySwapchainKHR(VkDevice device,VkSwapchainKHR swapchain_handle,const VkAllocationCallbacks * allocator)1392 void DestroySwapchainKHR(VkDevice device,
1393                          VkSwapchainKHR swapchain_handle,
1394                          const VkAllocationCallbacks* allocator) {
1395     ATRACE_CALL();
1396 
1397     const auto& dispatch = GetData(device).driver;
1398     Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
1399     if (!swapchain)
1400         return;
1401     bool active = swapchain->surface.swapchain_handle == swapchain_handle;
1402     ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
1403 
1404     if (window && swapchain->frame_timestamps_enabled) {
1405         native_window_enable_frame_timestamps(window, false);
1406     }
1407     for (uint32_t i = 0; i < swapchain->num_images; i++)
1408         ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
1409     if (active)
1410         swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
1411     if (!allocator)
1412         allocator = &GetData(device).allocator;
1413     swapchain->~Swapchain();
1414     allocator->pfnFree(allocator->pUserData, swapchain);
1415 }
1416 
1417 VKAPI_ATTR
GetSwapchainImagesKHR(VkDevice,VkSwapchainKHR swapchain_handle,uint32_t * count,VkImage * images)1418 VkResult GetSwapchainImagesKHR(VkDevice,
1419                                VkSwapchainKHR swapchain_handle,
1420                                uint32_t* count,
1421                                VkImage* images) {
1422     ATRACE_CALL();
1423 
1424     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
1425     ALOGW_IF(swapchain.surface.swapchain_handle != swapchain_handle,
1426              "getting images for non-active swapchain 0x%" PRIx64
1427              "; only dequeued image handles are valid",
1428              reinterpret_cast<uint64_t>(swapchain_handle));
1429     VkResult result = VK_SUCCESS;
1430     if (images) {
1431         uint32_t n = swapchain.num_images;
1432         if (*count < swapchain.num_images) {
1433             n = *count;
1434             result = VK_INCOMPLETE;
1435         }
1436         for (uint32_t i = 0; i < n; i++)
1437             images[i] = swapchain.images[i].image;
1438         *count = n;
1439     } else {
1440         *count = swapchain.num_images;
1441     }
1442     return result;
1443 }
1444 
1445 VKAPI_ATTR
AcquireNextImageKHR(VkDevice device,VkSwapchainKHR swapchain_handle,uint64_t timeout,VkSemaphore semaphore,VkFence vk_fence,uint32_t * image_index)1446 VkResult AcquireNextImageKHR(VkDevice device,
1447                              VkSwapchainKHR swapchain_handle,
1448                              uint64_t timeout,
1449                              VkSemaphore semaphore,
1450                              VkFence vk_fence,
1451                              uint32_t* image_index) {
1452     ATRACE_CALL();
1453 
1454     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
1455     ANativeWindow* window = swapchain.surface.window.get();
1456     VkResult result;
1457     int err;
1458 
1459     if (swapchain.surface.swapchain_handle != swapchain_handle)
1460         return VK_ERROR_OUT_OF_DATE_KHR;
1461 
1462     ALOGW_IF(
1463         timeout != UINT64_MAX,
1464         "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented");
1465 
1466     if (swapchain.shared) {
1467         // In shared mode, we keep the buffer dequeued all the time, so we don't
1468         // want to dequeue a buffer here. Instead, just ask the driver to ensure
1469         // the semaphore and fence passed to us will be signalled.
1470         *image_index = 0;
1471         result = GetData(device).driver.AcquireImageANDROID(
1472                 device, swapchain.images[*image_index].image, -1, semaphore, vk_fence);
1473         return result;
1474     }
1475 
1476     ANativeWindowBuffer* buffer;
1477     int fence_fd;
1478     err = window->dequeueBuffer(window, &buffer, &fence_fd);
1479     if (err != 0) {
1480         // TODO(jessehall): Improve error reporting. Can we enumerate possible
1481         // errors and translate them to valid Vulkan result codes?
1482         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
1483         return VK_ERROR_SURFACE_LOST_KHR;
1484     }
1485 
1486     uint32_t idx;
1487     for (idx = 0; idx < swapchain.num_images; idx++) {
1488         if (swapchain.images[idx].buffer.get() == buffer) {
1489             swapchain.images[idx].dequeued = true;
1490             swapchain.images[idx].dequeue_fence = fence_fd;
1491             break;
1492         }
1493     }
1494     if (idx == swapchain.num_images) {
1495         ALOGE("dequeueBuffer returned unrecognized buffer");
1496         window->cancelBuffer(window, buffer, fence_fd);
1497         return VK_ERROR_OUT_OF_DATE_KHR;
1498     }
1499 
1500     int fence_clone = -1;
1501     if (fence_fd != -1) {
1502         fence_clone = dup(fence_fd);
1503         if (fence_clone == -1) {
1504             ALOGE("dup(fence) failed, stalling until signalled: %s (%d)",
1505                   strerror(errno), errno);
1506             sync_wait(fence_fd, -1 /* forever */);
1507         }
1508     }
1509 
1510     result = GetData(device).driver.AcquireImageANDROID(
1511         device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence);
1512     if (result != VK_SUCCESS) {
1513         // NOTE: we're relying on AcquireImageANDROID to close fence_clone,
1514         // even if the call fails. We could close it ourselves on failure, but
1515         // that would create a race condition if the driver closes it on a
1516         // failure path: some other thread might create an fd with the same
1517         // number between the time the driver closes it and the time we close
1518         // it. We must assume one of: the driver *always* closes it even on
1519         // failure, or *never* closes it on failure.
1520         window->cancelBuffer(window, buffer, fence_fd);
1521         swapchain.images[idx].dequeued = false;
1522         swapchain.images[idx].dequeue_fence = -1;
1523         return result;
1524     }
1525 
1526     *image_index = idx;
1527     return VK_SUCCESS;
1528 }
1529 
1530 VKAPI_ATTR
AcquireNextImage2KHR(VkDevice device,const VkAcquireNextImageInfoKHR * pAcquireInfo,uint32_t * pImageIndex)1531 VkResult AcquireNextImage2KHR(VkDevice device,
1532                               const VkAcquireNextImageInfoKHR* pAcquireInfo,
1533                               uint32_t* pImageIndex) {
1534     ATRACE_CALL();
1535 
1536     // TODO: this should actually be the other way around and this function
1537     // should handle any additional structures that get passed in
1538     return AcquireNextImageKHR(device, pAcquireInfo->swapchain,
1539                                pAcquireInfo->timeout, pAcquireInfo->semaphore,
1540                                pAcquireInfo->fence, pImageIndex);
1541 }
1542 
WorstPresentResult(VkResult a,VkResult b)1543 static VkResult WorstPresentResult(VkResult a, VkResult b) {
1544     // See the error ranking for vkQueuePresentKHR at the end of section 29.6
1545     // (in spec version 1.0.14).
1546     static const VkResult kWorstToBest[] = {
1547         VK_ERROR_DEVICE_LOST,
1548         VK_ERROR_SURFACE_LOST_KHR,
1549         VK_ERROR_OUT_OF_DATE_KHR,
1550         VK_ERROR_OUT_OF_DEVICE_MEMORY,
1551         VK_ERROR_OUT_OF_HOST_MEMORY,
1552         VK_SUBOPTIMAL_KHR,
1553     };
1554     for (auto result : kWorstToBest) {
1555         if (a == result || b == result)
1556             return result;
1557     }
1558     ALOG_ASSERT(a == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", a);
1559     ALOG_ASSERT(b == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", b);
1560     return a != VK_SUCCESS ? a : b;
1561 }
1562 
1563 VKAPI_ATTR
QueuePresentKHR(VkQueue queue,const VkPresentInfoKHR * present_info)1564 VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
1565     ATRACE_CALL();
1566 
1567     ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1568              "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
1569              present_info->sType);
1570 
1571     VkDevice device = GetData(queue).driver_device;
1572     const auto& dispatch = GetData(queue).driver;
1573     VkResult final_result = VK_SUCCESS;
1574 
1575     // Look at the pNext chain for supported extension structs:
1576     const VkPresentRegionsKHR* present_regions = nullptr;
1577     const VkPresentTimesInfoGOOGLE* present_times = nullptr;
1578     const VkPresentRegionsKHR* next =
1579         reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext);
1580     while (next) {
1581         switch (next->sType) {
1582             case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
1583                 present_regions = next;
1584                 break;
1585             case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE:
1586                 present_times =
1587                     reinterpret_cast<const VkPresentTimesInfoGOOGLE*>(next);
1588                 break;
1589             default:
1590                 ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x",
1591                       next->sType);
1592                 break;
1593         }
1594         next = reinterpret_cast<const VkPresentRegionsKHR*>(next->pNext);
1595     }
1596     ALOGV_IF(
1597         present_regions &&
1598             present_regions->swapchainCount != present_info->swapchainCount,
1599         "VkPresentRegions::swapchainCount != VkPresentInfo::swapchainCount");
1600     ALOGV_IF(present_times &&
1601                  present_times->swapchainCount != present_info->swapchainCount,
1602              "VkPresentTimesInfoGOOGLE::swapchainCount != "
1603              "VkPresentInfo::swapchainCount");
1604     const VkPresentRegionKHR* regions =
1605         (present_regions) ? present_regions->pRegions : nullptr;
1606     const VkPresentTimeGOOGLE* times =
1607         (present_times) ? present_times->pTimes : nullptr;
1608     const VkAllocationCallbacks* allocator = &GetData(device).allocator;
1609     android_native_rect_t* rects = nullptr;
1610     uint32_t nrects = 0;
1611 
1612     for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
1613         Swapchain& swapchain =
1614             *SwapchainFromHandle(present_info->pSwapchains[sc]);
1615         uint32_t image_idx = present_info->pImageIndices[sc];
1616         Swapchain::Image& img = swapchain.images[image_idx];
1617         const VkPresentRegionKHR* region =
1618             (regions && !swapchain.mailbox_mode) ? &regions[sc] : nullptr;
1619         const VkPresentTimeGOOGLE* time = (times) ? &times[sc] : nullptr;
1620         VkResult swapchain_result = VK_SUCCESS;
1621         VkResult result;
1622         int err;
1623 
1624         int fence = -1;
1625         result = dispatch.QueueSignalReleaseImageANDROID(
1626             queue, present_info->waitSemaphoreCount,
1627             present_info->pWaitSemaphores, img.image, &fence);
1628         if (result != VK_SUCCESS) {
1629             ALOGE("QueueSignalReleaseImageANDROID failed: %d", result);
1630             swapchain_result = result;
1631         }
1632 
1633         if (swapchain.surface.swapchain_handle ==
1634             present_info->pSwapchains[sc]) {
1635             ANativeWindow* window = swapchain.surface.window.get();
1636             if (swapchain_result == VK_SUCCESS) {
1637                 if (region) {
1638                     // Process the incremental-present hint for this swapchain:
1639                     uint32_t rcount = region->rectangleCount;
1640                     if (rcount > nrects) {
1641                         android_native_rect_t* new_rects =
1642                             static_cast<android_native_rect_t*>(
1643                                 allocator->pfnReallocation(
1644                                     allocator->pUserData, rects,
1645                                     sizeof(android_native_rect_t) * rcount,
1646                                     alignof(android_native_rect_t),
1647                                     VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
1648                         if (new_rects) {
1649                             rects = new_rects;
1650                             nrects = rcount;
1651                         } else {
1652                             rcount = 0;  // Ignore the hint for this swapchain
1653                         }
1654                     }
1655                     for (uint32_t r = 0; r < rcount; ++r) {
1656                         if (region->pRectangles[r].layer > 0) {
1657                             ALOGV(
1658                                 "vkQueuePresentKHR ignoring invalid layer "
1659                                 "(%u); using layer 0 instead",
1660                                 region->pRectangles[r].layer);
1661                         }
1662                         int x = region->pRectangles[r].offset.x;
1663                         int y = region->pRectangles[r].offset.y;
1664                         int width = static_cast<int>(
1665                             region->pRectangles[r].extent.width);
1666                         int height = static_cast<int>(
1667                             region->pRectangles[r].extent.height);
1668                         android_native_rect_t* cur_rect = &rects[r];
1669                         cur_rect->left = x;
1670                         cur_rect->top = y + height;
1671                         cur_rect->right = x + width;
1672                         cur_rect->bottom = y;
1673                     }
1674                     native_window_set_surface_damage(window, rects, rcount);
1675                 }
1676                 if (time) {
1677                     if (!swapchain.frame_timestamps_enabled) {
1678                         ALOGV(
1679                             "Calling "
1680                             "native_window_enable_frame_timestamps(true)");
1681                         native_window_enable_frame_timestamps(window, true);
1682                         swapchain.frame_timestamps_enabled = true;
1683                     }
1684 
1685                     // Record the nativeFrameId so it can be later correlated to
1686                     // this present.
1687                     uint64_t nativeFrameId = 0;
1688                     err = native_window_get_next_frame_id(
1689                             window, &nativeFrameId);
1690                     if (err != android::NO_ERROR) {
1691                         ALOGE("Failed to get next native frame ID.");
1692                     }
1693 
1694                     // Add a new timing record with the user's presentID and
1695                     // the nativeFrameId.
1696                     swapchain.timing.push_back(TimingInfo(time, nativeFrameId));
1697                     while (swapchain.timing.size() > MAX_TIMING_INFOS) {
1698                         swapchain.timing.removeAt(0);
1699                     }
1700                     if (time->desiredPresentTime) {
1701                         // Set the desiredPresentTime:
1702                         ALOGV(
1703                             "Calling "
1704                             "native_window_set_buffers_timestamp(%" PRId64 ")",
1705                             time->desiredPresentTime);
1706                         native_window_set_buffers_timestamp(
1707                             window,
1708                             static_cast<int64_t>(time->desiredPresentTime));
1709                     }
1710                 }
1711 
1712                 err = window->queueBuffer(window, img.buffer.get(), fence);
1713                 // queueBuffer always closes fence, even on error
1714                 if (err != 0) {
1715                     // TODO(jessehall): What now? We should probably cancel the
1716                     // buffer, I guess?
1717                     ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
1718                     swapchain_result = WorstPresentResult(
1719                         swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
1720                 }
1721                 if (img.dequeue_fence >= 0) {
1722                     close(img.dequeue_fence);
1723                     img.dequeue_fence = -1;
1724                 }
1725                 img.dequeued = false;
1726 
1727                 // If the swapchain is in shared mode, immediately dequeue the
1728                 // buffer so it can be presented again without an intervening
1729                 // call to AcquireNextImageKHR. We expect to get the same buffer
1730                 // back from every call to dequeueBuffer in this mode.
1731                 if (swapchain.shared && swapchain_result == VK_SUCCESS) {
1732                     ANativeWindowBuffer* buffer;
1733                     int fence_fd;
1734                     err = window->dequeueBuffer(window, &buffer, &fence_fd);
1735                     if (err != 0) {
1736                         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
1737                         swapchain_result = WorstPresentResult(swapchain_result,
1738                             VK_ERROR_SURFACE_LOST_KHR);
1739                     }
1740                     else if (img.buffer != buffer) {
1741                         ALOGE("got wrong image back for shared swapchain");
1742                         swapchain_result = WorstPresentResult(swapchain_result,
1743                             VK_ERROR_SURFACE_LOST_KHR);
1744                     }
1745                     else {
1746                         img.dequeue_fence = fence_fd;
1747                         img.dequeued = true;
1748                     }
1749                 }
1750             }
1751             if (swapchain_result != VK_SUCCESS) {
1752                 ReleaseSwapchainImage(device, window, fence, img);
1753                 OrphanSwapchain(device, &swapchain);
1754             }
1755             int window_transform_hint;
1756             err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
1757                                 &window_transform_hint);
1758             if (err != 0) {
1759                 ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
1760                       strerror(-err), err);
1761                 swapchain_result = WorstPresentResult(
1762                     swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
1763             }
1764             if (swapchain.pre_transform != window_transform_hint) {
1765                 swapchain_result =
1766                     WorstPresentResult(swapchain_result, VK_SUBOPTIMAL_KHR);
1767             }
1768         } else {
1769             ReleaseSwapchainImage(device, nullptr, fence, img);
1770             swapchain_result = VK_ERROR_OUT_OF_DATE_KHR;
1771         }
1772 
1773         if (present_info->pResults)
1774             present_info->pResults[sc] = swapchain_result;
1775 
1776         if (swapchain_result != final_result)
1777             final_result = WorstPresentResult(final_result, swapchain_result);
1778     }
1779     if (rects) {
1780         allocator->pfnFree(allocator->pUserData, rects);
1781     }
1782 
1783     return final_result;
1784 }
1785 
1786 VKAPI_ATTR
GetRefreshCycleDurationGOOGLE(VkDevice,VkSwapchainKHR swapchain_handle,VkRefreshCycleDurationGOOGLE * pDisplayTimingProperties)1787 VkResult GetRefreshCycleDurationGOOGLE(
1788     VkDevice,
1789     VkSwapchainKHR swapchain_handle,
1790     VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
1791     ATRACE_CALL();
1792 
1793     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
1794     VkResult result = VK_SUCCESS;
1795 
1796     pDisplayTimingProperties->refreshDuration = swapchain.get_refresh_duration();
1797 
1798     return result;
1799 }
1800 
1801 VKAPI_ATTR
GetPastPresentationTimingGOOGLE(VkDevice,VkSwapchainKHR swapchain_handle,uint32_t * count,VkPastPresentationTimingGOOGLE * timings)1802 VkResult GetPastPresentationTimingGOOGLE(
1803     VkDevice,
1804     VkSwapchainKHR swapchain_handle,
1805     uint32_t* count,
1806     VkPastPresentationTimingGOOGLE* timings) {
1807     ATRACE_CALL();
1808 
1809     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
1810     ANativeWindow* window = swapchain.surface.window.get();
1811     VkResult result = VK_SUCCESS;
1812 
1813     if (!swapchain.frame_timestamps_enabled) {
1814         ALOGV("Calling native_window_enable_frame_timestamps(true)");
1815         native_window_enable_frame_timestamps(window, true);
1816         swapchain.frame_timestamps_enabled = true;
1817     }
1818 
1819     if (timings) {
1820         // TODO(ianelliott): plumb return value (e.g. VK_INCOMPLETE)
1821         copy_ready_timings(swapchain, count, timings);
1822     } else {
1823         *count = get_num_ready_timings(swapchain);
1824     }
1825 
1826     return result;
1827 }
1828 
1829 VKAPI_ATTR
GetSwapchainStatusKHR(VkDevice,VkSwapchainKHR swapchain_handle)1830 VkResult GetSwapchainStatusKHR(
1831     VkDevice,
1832     VkSwapchainKHR swapchain_handle) {
1833     ATRACE_CALL();
1834 
1835     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
1836     VkResult result = VK_SUCCESS;
1837 
1838     if (swapchain.surface.swapchain_handle != swapchain_handle) {
1839         return VK_ERROR_OUT_OF_DATE_KHR;
1840     }
1841 
1842     // TODO(chrisforbes): Implement this function properly
1843 
1844     return result;
1845 }
1846 
SetHdrMetadataEXT(VkDevice,uint32_t swapchainCount,const VkSwapchainKHR * pSwapchains,const VkHdrMetadataEXT * pHdrMetadataEXTs)1847 VKAPI_ATTR void SetHdrMetadataEXT(
1848     VkDevice,
1849     uint32_t swapchainCount,
1850     const VkSwapchainKHR* pSwapchains,
1851     const VkHdrMetadataEXT* pHdrMetadataEXTs) {
1852     ATRACE_CALL();
1853 
1854     for (uint32_t idx = 0; idx < swapchainCount; idx++) {
1855         Swapchain* swapchain = SwapchainFromHandle(pSwapchains[idx]);
1856         if (!swapchain)
1857             continue;
1858 
1859         if (swapchain->surface.swapchain_handle != pSwapchains[idx]) continue;
1860 
1861         ANativeWindow* window = swapchain->surface.window.get();
1862 
1863         VkHdrMetadataEXT vulkanMetadata = pHdrMetadataEXTs[idx];
1864         const android_smpte2086_metadata smpteMetdata = {
1865             {vulkanMetadata.displayPrimaryRed.x,
1866              vulkanMetadata.displayPrimaryRed.y},
1867             {vulkanMetadata.displayPrimaryGreen.x,
1868              vulkanMetadata.displayPrimaryGreen.y},
1869             {vulkanMetadata.displayPrimaryBlue.x,
1870              vulkanMetadata.displayPrimaryBlue.y},
1871             {vulkanMetadata.whitePoint.x, vulkanMetadata.whitePoint.y},
1872             vulkanMetadata.maxLuminance,
1873             vulkanMetadata.minLuminance};
1874         native_window_set_buffers_smpte2086_metadata(window, &smpteMetdata);
1875 
1876         const android_cta861_3_metadata cta8613Metadata = {
1877             vulkanMetadata.maxContentLightLevel,
1878             vulkanMetadata.maxFrameAverageLightLevel};
1879         native_window_set_buffers_cta861_3_metadata(window, &cta8613Metadata);
1880     }
1881 
1882     return;
1883 }
1884 
InterceptBindImageMemory2(uint32_t bind_info_count,const VkBindImageMemoryInfo * bind_infos,std::vector<VkNativeBufferANDROID> * out_native_buffers,std::vector<VkBindImageMemoryInfo> * out_bind_infos)1885 static void InterceptBindImageMemory2(
1886     uint32_t bind_info_count,
1887     const VkBindImageMemoryInfo* bind_infos,
1888     std::vector<VkNativeBufferANDROID>* out_native_buffers,
1889     std::vector<VkBindImageMemoryInfo>* out_bind_infos) {
1890     out_native_buffers->clear();
1891     out_bind_infos->clear();
1892 
1893     if (!bind_info_count)
1894         return;
1895 
1896     std::unordered_set<uint32_t> intercepted_indexes;
1897 
1898     for (uint32_t idx = 0; idx < bind_info_count; idx++) {
1899         auto info = reinterpret_cast<const VkBindImageMemorySwapchainInfoKHR*>(
1900             bind_infos[idx].pNext);
1901         while (info &&
1902                info->sType !=
1903                    VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR) {
1904             info = reinterpret_cast<const VkBindImageMemorySwapchainInfoKHR*>(
1905                 info->pNext);
1906         }
1907 
1908         if (!info)
1909             continue;
1910 
1911         ALOG_ASSERT(info->swapchain != VK_NULL_HANDLE,
1912                     "swapchain handle must not be NULL");
1913         const Swapchain* swapchain = SwapchainFromHandle(info->swapchain);
1914         ALOG_ASSERT(
1915             info->imageIndex < swapchain->num_images,
1916             "imageIndex must be less than the number of images in swapchain");
1917 
1918         ANativeWindowBuffer* buffer =
1919             swapchain->images[info->imageIndex].buffer.get();
1920         VkNativeBufferANDROID native_buffer = {
1921 #pragma clang diagnostic push
1922 #pragma clang diagnostic ignored "-Wold-style-cast"
1923             .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
1924 #pragma clang diagnostic pop
1925             .pNext = bind_infos[idx].pNext,
1926             .handle = buffer->handle,
1927             .stride = buffer->stride,
1928             .format = buffer->format,
1929             .usage = int(buffer->usage),
1930         };
1931         // Reserve enough space to avoid letting re-allocation invalidate the
1932         // addresses of the elements inside.
1933         out_native_buffers->reserve(bind_info_count);
1934         out_native_buffers->emplace_back(native_buffer);
1935 
1936         // Reserve the space now since we know how much is needed now.
1937         out_bind_infos->reserve(bind_info_count);
1938         out_bind_infos->emplace_back(bind_infos[idx]);
1939         out_bind_infos->back().pNext = &out_native_buffers->back();
1940 
1941         intercepted_indexes.insert(idx);
1942     }
1943 
1944     if (intercepted_indexes.empty())
1945         return;
1946 
1947     for (uint32_t idx = 0; idx < bind_info_count; idx++) {
1948         if (intercepted_indexes.count(idx))
1949             continue;
1950         out_bind_infos->emplace_back(bind_infos[idx]);
1951     }
1952 }
1953 
1954 VKAPI_ATTR
BindImageMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1955 VkResult BindImageMemory2(VkDevice device,
1956                           uint32_t bindInfoCount,
1957                           const VkBindImageMemoryInfo* pBindInfos) {
1958     ATRACE_CALL();
1959 
1960     // out_native_buffers is for maintaining the lifecycle of the constructed
1961     // VkNativeBufferANDROID objects inside InterceptBindImageMemory2.
1962     std::vector<VkNativeBufferANDROID> out_native_buffers;
1963     std::vector<VkBindImageMemoryInfo> out_bind_infos;
1964     InterceptBindImageMemory2(bindInfoCount, pBindInfos, &out_native_buffers,
1965                               &out_bind_infos);
1966     return GetData(device).driver.BindImageMemory2(
1967         device, bindInfoCount,
1968         out_bind_infos.empty() ? pBindInfos : out_bind_infos.data());
1969 }
1970 
1971 VKAPI_ATTR
BindImageMemory2KHR(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1972 VkResult BindImageMemory2KHR(VkDevice device,
1973                              uint32_t bindInfoCount,
1974                              const VkBindImageMemoryInfo* pBindInfos) {
1975     ATRACE_CALL();
1976 
1977     std::vector<VkNativeBufferANDROID> out_native_buffers;
1978     std::vector<VkBindImageMemoryInfo> out_bind_infos;
1979     InterceptBindImageMemory2(bindInfoCount, pBindInfos, &out_native_buffers,
1980                               &out_bind_infos);
1981     return GetData(device).driver.BindImageMemory2KHR(
1982         device, bindInfoCount,
1983         out_bind_infos.empty() ? pBindInfos : out_bind_infos.data());
1984 }
1985 
1986 }  // namespace driver
1987 }  // namespace vulkan
1988