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