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 <graphicsenv/GraphicsEnv.h>
22 #include <hardware/gralloc.h>
23 #include <hardware/gralloc1.h>
24 #include <log/log.h>
25 #include <sync/sync.h>
26 #include <system/window.h>
27 #include <ui/BufferQueueDefs.h>
28 #include <ui/DebugUtils.h>
29 #include <ui/PixelFormat.h>
30 #include <utils/StrongPointer.h>
31 #include <utils/Timers.h>
32 #include <utils/Trace.h>
33
34 #include <algorithm>
35 #include <unordered_set>
36 #include <vector>
37
38 #include "driver.h"
39
40 using android::hardware::graphics::common::V1_0::BufferUsage;
41
42 namespace vulkan {
43 namespace driver {
44
45 namespace {
46
convertGralloc1ToBufferUsage(uint64_t producerUsage,uint64_t consumerUsage)47 static uint64_t convertGralloc1ToBufferUsage(uint64_t producerUsage,
48 uint64_t consumerUsage) {
49 static_assert(uint64_t(GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) ==
50 uint64_t(GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN),
51 "expected ConsumerUsage and ProducerUsage CPU_READ_OFTEN "
52 "bits to match");
53 uint64_t merged = producerUsage | consumerUsage;
54 if ((merged & (GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN)) ==
55 GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) {
56 merged &= ~uint64_t(GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN);
57 merged |= BufferUsage::CPU_READ_OFTEN;
58 }
59 if ((merged & (GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN)) ==
60 GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) {
61 merged &= ~uint64_t(GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN);
62 merged |= BufferUsage::CPU_WRITE_OFTEN;
63 }
64 return merged;
65 }
66
67 const VkSurfaceTransformFlagsKHR kSupportedTransforms =
68 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR |
69 VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
70 VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR |
71 VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR |
72 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
73 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
74 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
75 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
76 VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
77
TranslateNativeToVulkanTransform(int native)78 VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) {
79 // Native and Vulkan transforms are isomorphic, but are represented
80 // differently. Vulkan transforms are built up of an optional horizontal
81 // mirror, followed by a clockwise 0/90/180/270-degree rotation. Native
82 // transforms are built up from a horizontal flip, vertical flip, and
83 // 90-degree rotation, all optional but always in that order.
84
85 switch (native) {
86 case 0:
87 return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
88 case NATIVE_WINDOW_TRANSFORM_FLIP_H:
89 return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
90 case NATIVE_WINDOW_TRANSFORM_FLIP_V:
91 return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
92 case NATIVE_WINDOW_TRANSFORM_ROT_180:
93 return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
94 case NATIVE_WINDOW_TRANSFORM_ROT_90:
95 return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
96 case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
97 return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
98 case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
99 return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
100 case NATIVE_WINDOW_TRANSFORM_ROT_270:
101 return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
102 case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
103 default:
104 return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
105 }
106 }
107
TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform)108 int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) {
109 switch (transform) {
110 case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
111 return NATIVE_WINDOW_TRANSFORM_ROT_90;
112 case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
113 return NATIVE_WINDOW_TRANSFORM_ROT_180;
114 case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
115 return NATIVE_WINDOW_TRANSFORM_ROT_270;
116 case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
117 return NATIVE_WINDOW_TRANSFORM_FLIP_H;
118 case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
119 return NATIVE_WINDOW_TRANSFORM_FLIP_H |
120 NATIVE_WINDOW_TRANSFORM_ROT_90;
121 case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
122 return NATIVE_WINDOW_TRANSFORM_FLIP_V;
123 case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
124 return NATIVE_WINDOW_TRANSFORM_FLIP_V |
125 NATIVE_WINDOW_TRANSFORM_ROT_90;
126 case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
127 case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
128 default:
129 return 0;
130 }
131 }
132
InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform)133 int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) {
134 switch (transform) {
135 case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
136 return NATIVE_WINDOW_TRANSFORM_ROT_270;
137 case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
138 return NATIVE_WINDOW_TRANSFORM_ROT_180;
139 case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
140 return NATIVE_WINDOW_TRANSFORM_ROT_90;
141 case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
142 return NATIVE_WINDOW_TRANSFORM_FLIP_H;
143 case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
144 return NATIVE_WINDOW_TRANSFORM_FLIP_H |
145 NATIVE_WINDOW_TRANSFORM_ROT_90;
146 case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
147 return NATIVE_WINDOW_TRANSFORM_FLIP_V;
148 case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
149 return NATIVE_WINDOW_TRANSFORM_FLIP_V |
150 NATIVE_WINDOW_TRANSFORM_ROT_90;
151 case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
152 case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
153 default:
154 return 0;
155 }
156 }
157
158 class TimingInfo {
159 public:
TimingInfo(const VkPresentTimeGOOGLE * qp,uint64_t nativeFrameId)160 TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId)
161 : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
162 native_frame_id_(nativeFrameId) {}
ready() const163 bool ready() const {
164 return (timestamp_desired_present_time_ !=
165 NATIVE_WINDOW_TIMESTAMP_PENDING &&
166 timestamp_actual_present_time_ !=
167 NATIVE_WINDOW_TIMESTAMP_PENDING &&
168 timestamp_render_complete_time_ !=
169 NATIVE_WINDOW_TIMESTAMP_PENDING &&
170 timestamp_composition_latch_time_ !=
171 NATIVE_WINDOW_TIMESTAMP_PENDING);
172 }
calculate(int64_t rdur)173 void calculate(int64_t rdur) {
174 bool anyTimestampInvalid =
175 (timestamp_actual_present_time_ ==
176 NATIVE_WINDOW_TIMESTAMP_INVALID) ||
177 (timestamp_render_complete_time_ ==
178 NATIVE_WINDOW_TIMESTAMP_INVALID) ||
179 (timestamp_composition_latch_time_ ==
180 NATIVE_WINDOW_TIMESTAMP_INVALID);
181 if (anyTimestampInvalid) {
182 ALOGE("Unexpectedly received invalid timestamp.");
183 vals_.actualPresentTime = 0;
184 vals_.earliestPresentTime = 0;
185 vals_.presentMargin = 0;
186 return;
187 }
188
189 vals_.actualPresentTime =
190 static_cast<uint64_t>(timestamp_actual_present_time_);
191 int64_t margin = (timestamp_composition_latch_time_ -
192 timestamp_render_complete_time_);
193 // Calculate vals_.earliestPresentTime, and potentially adjust
194 // vals_.presentMargin. The initial value of vals_.earliestPresentTime
195 // is vals_.actualPresentTime. If we can subtract rdur (the duration
196 // of a refresh cycle) from vals_.earliestPresentTime (and also from
197 // vals_.presentMargin) and still leave a positive margin, then we can
198 // report to the application that it could have presented earlier than
199 // it did (per the extension specification). If for some reason, we
200 // can do this subtraction repeatedly, we do, since
201 // vals_.earliestPresentTime really is supposed to be the "earliest".
202 int64_t early_time = timestamp_actual_present_time_;
203 while ((margin > rdur) &&
204 ((early_time - rdur) > timestamp_composition_latch_time_)) {
205 early_time -= rdur;
206 margin -= rdur;
207 }
208 vals_.earliestPresentTime = static_cast<uint64_t>(early_time);
209 vals_.presentMargin = static_cast<uint64_t>(margin);
210 }
get_values(VkPastPresentationTimingGOOGLE * values) const211 void get_values(VkPastPresentationTimingGOOGLE* values) const {
212 *values = vals_;
213 }
214
215 public:
216 VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
217
218 uint64_t native_frame_id_ { 0 };
219 int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING };
220 int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
221 int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
222 int64_t timestamp_composition_latch_time_
223 { NATIVE_WINDOW_TIMESTAMP_PENDING };
224 };
225
226 struct Surface {
227 android::sp<ANativeWindow> window;
228 VkSwapchainKHR swapchain_handle;
229 uint64_t consumer_usage;
230
231 // Indicate whether this surface has been used by a swapchain, no matter the
232 // swapchain is still current or has been destroyed.
233 bool used_by_swapchain;
234 };
235
HandleFromSurface(Surface * surface)236 VkSurfaceKHR HandleFromSurface(Surface* surface) {
237 return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface));
238 }
239
SurfaceFromHandle(VkSurfaceKHR handle)240 Surface* SurfaceFromHandle(VkSurfaceKHR handle) {
241 return reinterpret_cast<Surface*>(handle);
242 }
243
244 // Maximum number of TimingInfo structs to keep per swapchain:
245 enum { MAX_TIMING_INFOS = 10 };
246 // Minimum number of frames to look for in the past (so we don't cause
247 // syncronous requests to Surface Flinger):
248 enum { MIN_NUM_FRAMES_AGO = 5 };
249
IsSharedPresentMode(VkPresentModeKHR mode)250 bool IsSharedPresentMode(VkPresentModeKHR mode) {
251 return mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
252 mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR;
253 }
254
255 struct Swapchain {
Swapchainvulkan::driver::__anonba7038700111::Swapchain256 Swapchain(Surface& surface_,
257 uint32_t num_images_,
258 VkPresentModeKHR present_mode,
259 int pre_transform_,
260 int64_t refresh_duration_)
261 : surface(surface_),
262 num_images(num_images_),
263 mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR),
264 pre_transform(pre_transform_),
265 frame_timestamps_enabled(false),
266 refresh_duration(refresh_duration_),
267 acquire_next_image_timeout(-1),
268 shared(IsSharedPresentMode(present_mode)) {
269 }
270
get_refresh_durationvulkan::driver::__anonba7038700111::Swapchain271 VkResult get_refresh_duration(uint64_t& outRefreshDuration)
272 {
273 ANativeWindow* window = surface.window.get();
274 int err = native_window_get_refresh_cycle_duration(
275 window,
276 &refresh_duration);
277 if (err != android::OK) {
278 ALOGE("%s:native_window_get_refresh_cycle_duration failed: %s (%d)",
279 __func__, strerror(-err), err );
280 return VK_ERROR_SURFACE_LOST_KHR;
281 }
282 outRefreshDuration = refresh_duration;
283 return VK_SUCCESS;
284 }
285
286 Surface& surface;
287 uint32_t num_images;
288 bool mailbox_mode;
289 int pre_transform;
290 bool frame_timestamps_enabled;
291 int64_t refresh_duration;
292 nsecs_t acquire_next_image_timeout;
293 bool shared;
294
295 struct Image {
Imagevulkan::driver::__anonba7038700111::Swapchain::Image296 Image()
297 : image(VK_NULL_HANDLE),
298 dequeue_fence(-1),
299 release_fence(-1),
300 dequeued(false) {}
301 VkImage image;
302 // If the image is bound to memory, an sp to the underlying gralloc buffer.
303 // Otherwise, nullptr; the image will be bound to memory as part of
304 // AcquireNextImage.
305 android::sp<ANativeWindowBuffer> buffer;
306 // The fence is only valid when the buffer is dequeued, and should be
307 // -1 any other time. When valid, we own the fd, and must ensure it is
308 // closed: either by closing it explicitly when queueing the buffer,
309 // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
310 int dequeue_fence;
311 // This fence is a dup of the sync fd returned from the driver via
312 // vkQueueSignalReleaseImageANDROID upon vkQueuePresentKHR. We must
313 // ensure it is closed upon re-presenting or releasing the image.
314 int release_fence;
315 bool dequeued;
316 } images[android::BufferQueueDefs::NUM_BUFFER_SLOTS];
317
318 std::vector<TimingInfo> timing;
319 };
320
HandleFromSwapchain(Swapchain * swapchain)321 VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
322 return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain));
323 }
324
SwapchainFromHandle(VkSwapchainKHR handle)325 Swapchain* SwapchainFromHandle(VkSwapchainKHR handle) {
326 return reinterpret_cast<Swapchain*>(handle);
327 }
328
IsFencePending(int fd)329 static bool IsFencePending(int fd) {
330 if (fd < 0)
331 return false;
332
333 errno = 0;
334 return sync_wait(fd, 0 /* timeout */) == -1 && errno == ETIME;
335 }
336
ReleaseSwapchainImage(VkDevice device,bool shared_present,ANativeWindow * window,int release_fence,Swapchain::Image & image,bool defer_if_pending)337 void ReleaseSwapchainImage(VkDevice device,
338 bool shared_present,
339 ANativeWindow* window,
340 int release_fence,
341 Swapchain::Image& image,
342 bool defer_if_pending) {
343 ATRACE_CALL();
344
345 ALOG_ASSERT(release_fence == -1 || image.dequeued,
346 "ReleaseSwapchainImage: can't provide a release fence for "
347 "non-dequeued images");
348
349 if (image.dequeued) {
350 if (release_fence >= 0) {
351 // We get here from vkQueuePresentKHR. The application is
352 // responsible for creating an execution dependency chain from
353 // vkAcquireNextImage (dequeue_fence) to vkQueuePresentKHR
354 // (release_fence), so we can drop the dequeue_fence here.
355 if (image.dequeue_fence >= 0)
356 close(image.dequeue_fence);
357 } else {
358 // We get here during swapchain destruction, or various serious
359 // error cases e.g. when we can't create the release_fence during
360 // vkQueuePresentKHR. In non-error cases, the dequeue_fence should
361 // have already signalled, since the swapchain images are supposed
362 // to be idle before the swapchain is destroyed. In error cases,
363 // there may be rendering in flight to the image, but since we
364 // weren't able to create a release_fence, waiting for the
365 // dequeue_fence is about the best we can do.
366 release_fence = image.dequeue_fence;
367 }
368 image.dequeue_fence = -1;
369
370 // It's invalid to call cancelBuffer on a shared buffer
371 if (window && !shared_present) {
372 window->cancelBuffer(window, image.buffer.get(), release_fence);
373 } else {
374 if (release_fence >= 0) {
375 sync_wait(release_fence, -1 /* forever */);
376 close(release_fence);
377 }
378 }
379 release_fence = -1;
380 image.dequeued = false;
381 }
382
383 if (defer_if_pending && IsFencePending(image.release_fence))
384 return;
385
386 if (image.release_fence >= 0) {
387 close(image.release_fence);
388 image.release_fence = -1;
389 }
390
391 if (image.image) {
392 ATRACE_BEGIN("DestroyImage");
393 GetData(device).driver.DestroyImage(device, image.image, nullptr);
394 ATRACE_END();
395 image.image = VK_NULL_HANDLE;
396 }
397
398 image.buffer.clear();
399 }
400
OrphanSwapchain(VkDevice device,Swapchain * swapchain)401 void OrphanSwapchain(VkDevice device, Swapchain* swapchain) {
402 if (swapchain->surface.swapchain_handle != HandleFromSwapchain(swapchain))
403 return;
404 for (uint32_t i = 0; i < swapchain->num_images; i++) {
405 if (!swapchain->images[i].dequeued) {
406 ReleaseSwapchainImage(device, swapchain->shared, nullptr, -1,
407 swapchain->images[i], true);
408 }
409 }
410 swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
411 swapchain->timing.clear();
412 }
413
get_num_ready_timings(Swapchain & swapchain)414 uint32_t get_num_ready_timings(Swapchain& swapchain) {
415 if (swapchain.timing.size() < MIN_NUM_FRAMES_AGO) {
416 return 0;
417 }
418
419 uint32_t num_ready = 0;
420 const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1;
421 for (uint32_t i = 0; i < num_timings; i++) {
422 TimingInfo& ti = swapchain.timing[i];
423 if (ti.ready()) {
424 // This TimingInfo is ready to be reported to the user. Add it
425 // to the num_ready.
426 num_ready++;
427 continue;
428 }
429 // This TimingInfo is not yet ready to be reported to the user,
430 // and so we should look for any available timestamps that
431 // might make it ready.
432 int64_t desired_present_time = 0;
433 int64_t render_complete_time = 0;
434 int64_t composition_latch_time = 0;
435 int64_t actual_present_time = 0;
436 // Obtain timestamps:
437 int err = native_window_get_frame_timestamps(
438 swapchain.surface.window.get(), ti.native_frame_id_,
439 &desired_present_time, &render_complete_time,
440 &composition_latch_time,
441 nullptr, //&first_composition_start_time,
442 nullptr, //&last_composition_start_time,
443 nullptr, //&composition_finish_time,
444 &actual_present_time,
445 nullptr, //&dequeue_ready_time,
446 nullptr /*&reads_done_time*/);
447
448 if (err != android::OK) {
449 continue;
450 }
451
452 // Record the timestamp(s) we received, and then see if this TimingInfo
453 // is ready to be reported to the user:
454 ti.timestamp_desired_present_time_ = desired_present_time;
455 ti.timestamp_actual_present_time_ = actual_present_time;
456 ti.timestamp_render_complete_time_ = render_complete_time;
457 ti.timestamp_composition_latch_time_ = composition_latch_time;
458
459 if (ti.ready()) {
460 // The TimingInfo has received enough timestamps, and should now
461 // use those timestamps to calculate the info that should be
462 // reported to the user:
463 ti.calculate(swapchain.refresh_duration);
464 num_ready++;
465 }
466 }
467 return num_ready;
468 }
469
copy_ready_timings(Swapchain & swapchain,uint32_t * count,VkPastPresentationTimingGOOGLE * timings)470 void copy_ready_timings(Swapchain& swapchain,
471 uint32_t* count,
472 VkPastPresentationTimingGOOGLE* timings) {
473 if (swapchain.timing.empty()) {
474 *count = 0;
475 return;
476 }
477
478 size_t last_ready = swapchain.timing.size() - 1;
479 while (!swapchain.timing[last_ready].ready()) {
480 if (last_ready == 0) {
481 *count = 0;
482 return;
483 }
484 last_ready--;
485 }
486
487 uint32_t num_copied = 0;
488 int32_t num_to_remove = 0;
489 for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) {
490 const TimingInfo& ti = swapchain.timing[i];
491 if (ti.ready()) {
492 ti.get_values(&timings[num_copied]);
493 num_copied++;
494 }
495 num_to_remove++;
496 }
497
498 // Discard old frames that aren't ready if newer frames are ready.
499 // We don't expect to get the timing info for those old frames.
500 swapchain.timing.erase(swapchain.timing.begin(),
501 swapchain.timing.begin() + num_to_remove);
502
503 *count = num_copied;
504 }
505
GetNativePixelFormat(VkFormat format)506 android::PixelFormat GetNativePixelFormat(VkFormat format) {
507 android::PixelFormat native_format = android::PIXEL_FORMAT_RGBA_8888;
508 switch (format) {
509 case VK_FORMAT_R8G8B8A8_UNORM:
510 case VK_FORMAT_R8G8B8A8_SRGB:
511 native_format = android::PIXEL_FORMAT_RGBA_8888;
512 break;
513 case VK_FORMAT_R5G6B5_UNORM_PACK16:
514 native_format = android::PIXEL_FORMAT_RGB_565;
515 break;
516 case VK_FORMAT_R16G16B16A16_SFLOAT:
517 native_format = android::PIXEL_FORMAT_RGBA_FP16;
518 break;
519 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
520 native_format = android::PIXEL_FORMAT_RGBA_1010102;
521 break;
522 case VK_FORMAT_R8_UNORM:
523 native_format = android::PIXEL_FORMAT_R_8;
524 break;
525 case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
526 native_format = android::PIXEL_FORMAT_RGBA_10101010;
527 break;
528 default:
529 ALOGV("unsupported swapchain format %d", format);
530 break;
531 }
532 return native_format;
533 }
534
GetNativeDataspace(VkColorSpaceKHR colorspace,android::PixelFormat pixelFormat)535 android_dataspace GetNativeDataspace(VkColorSpaceKHR colorspace,
536 android::PixelFormat pixelFormat) {
537 switch (colorspace) {
538 case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR:
539 return HAL_DATASPACE_V0_SRGB;
540 case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT:
541 return HAL_DATASPACE_DISPLAY_P3;
542 case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
543 return HAL_DATASPACE_V0_SCRGB_LINEAR;
544 case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT:
545 return HAL_DATASPACE_V0_SCRGB;
546 case VK_COLOR_SPACE_DCI_P3_LINEAR_EXT:
547 return HAL_DATASPACE_DCI_P3_LINEAR;
548 case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT:
549 return HAL_DATASPACE_DCI_P3;
550 case VK_COLOR_SPACE_BT709_LINEAR_EXT:
551 return HAL_DATASPACE_V0_SRGB_LINEAR;
552 case VK_COLOR_SPACE_BT709_NONLINEAR_EXT:
553 return HAL_DATASPACE_V0_SRGB;
554 case VK_COLOR_SPACE_BT2020_LINEAR_EXT:
555 if (pixelFormat == HAL_PIXEL_FORMAT_RGBA_FP16) {
556 return static_cast<android_dataspace>(
557 HAL_DATASPACE_STANDARD_BT2020 |
558 HAL_DATASPACE_TRANSFER_LINEAR |
559 HAL_DATASPACE_RANGE_EXTENDED);
560 } else {
561 return HAL_DATASPACE_BT2020_LINEAR;
562 }
563 case VK_COLOR_SPACE_HDR10_ST2084_EXT:
564 return static_cast<android_dataspace>(
565 HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
566 HAL_DATASPACE_RANGE_FULL);
567 case VK_COLOR_SPACE_DOLBYVISION_EXT:
568 return static_cast<android_dataspace>(
569 HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
570 HAL_DATASPACE_RANGE_FULL);
571 case VK_COLOR_SPACE_HDR10_HLG_EXT:
572 return static_cast<android_dataspace>(HAL_DATASPACE_BT2020_HLG);
573 case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT:
574 return static_cast<android_dataspace>(
575 HAL_DATASPACE_STANDARD_ADOBE_RGB |
576 HAL_DATASPACE_TRANSFER_LINEAR | HAL_DATASPACE_RANGE_FULL);
577 case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT:
578 return HAL_DATASPACE_ADOBE_RGB;
579
580 // Pass through is intended to allow app to provide data that is passed
581 // to the display system without modification.
582 case VK_COLOR_SPACE_PASS_THROUGH_EXT:
583 return HAL_DATASPACE_ARBITRARY;
584
585 default:
586 // This indicates that we don't know about the
587 // dataspace specified and we should indicate that
588 // it's unsupported
589 return HAL_DATASPACE_UNKNOWN;
590 }
591 }
592
593 } // anonymous namespace
594
595 VKAPI_ATTR
CreateAndroidSurfaceKHR(VkInstance instance,const VkAndroidSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * allocator,VkSurfaceKHR * out_surface)596 VkResult CreateAndroidSurfaceKHR(
597 VkInstance instance,
598 const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
599 const VkAllocationCallbacks* allocator,
600 VkSurfaceKHR* out_surface) {
601 ATRACE_CALL();
602
603 if (!allocator)
604 allocator = &GetData(instance).allocator;
605 void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Surface),
606 alignof(Surface),
607 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
608 if (!mem)
609 return VK_ERROR_OUT_OF_HOST_MEMORY;
610 Surface* surface = new (mem) Surface;
611
612 surface->window = pCreateInfo->window;
613 surface->swapchain_handle = VK_NULL_HANDLE;
614 surface->used_by_swapchain = false;
615 int err = native_window_get_consumer_usage(surface->window.get(),
616 &surface->consumer_usage);
617 if (err != android::OK) {
618 ALOGE("native_window_get_consumer_usage() failed: %s (%d)",
619 strerror(-err), err);
620 surface->~Surface();
621 allocator->pfnFree(allocator->pUserData, surface);
622 return VK_ERROR_SURFACE_LOST_KHR;
623 }
624
625 err =
626 native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
627 if (err != android::OK) {
628 ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
629 err);
630 surface->~Surface();
631 allocator->pfnFree(allocator->pUserData, surface);
632 return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
633 }
634
635 *out_surface = HandleFromSurface(surface);
636 return VK_SUCCESS;
637 }
638
639 VKAPI_ATTR
DestroySurfaceKHR(VkInstance instance,VkSurfaceKHR surface_handle,const VkAllocationCallbacks * allocator)640 void DestroySurfaceKHR(VkInstance instance,
641 VkSurfaceKHR surface_handle,
642 const VkAllocationCallbacks* allocator) {
643 ATRACE_CALL();
644
645 Surface* surface = SurfaceFromHandle(surface_handle);
646 if (!surface)
647 return;
648 native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL);
649 ALOGV_IF(surface->swapchain_handle != VK_NULL_HANDLE,
650 "destroyed VkSurfaceKHR 0x%" PRIx64
651 " has active VkSwapchainKHR 0x%" PRIx64,
652 reinterpret_cast<uint64_t>(surface_handle),
653 reinterpret_cast<uint64_t>(surface->swapchain_handle));
654 surface->~Surface();
655 if (!allocator)
656 allocator = &GetData(instance).allocator;
657 allocator->pfnFree(allocator->pUserData, surface);
658 }
659
660 VKAPI_ATTR
GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice,uint32_t,VkSurfaceKHR,VkBool32 * supported)661 VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
662 uint32_t /*queue_family*/,
663 VkSurfaceKHR /*surface_handle*/,
664 VkBool32* supported) {
665 *supported = VK_TRUE;
666 return VK_SUCCESS;
667 }
668
669 VKAPI_ATTR
GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice pdev,VkSurfaceKHR surface,VkSurfaceCapabilitiesKHR * capabilities)670 VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
671 VkPhysicalDevice pdev,
672 VkSurfaceKHR surface,
673 VkSurfaceCapabilitiesKHR* capabilities) {
674 ATRACE_CALL();
675
676 // Implement in terms of GetPhysicalDeviceSurfaceCapabilities2KHR
677
678 VkPhysicalDeviceSurfaceInfo2KHR info2 = {
679 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
680 nullptr,
681 surface
682 };
683
684 VkSurfaceCapabilities2KHR caps2 = {
685 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
686 nullptr,
687 {},
688 };
689
690 VkResult result = GetPhysicalDeviceSurfaceCapabilities2KHR(pdev, &info2, &caps2);
691 *capabilities = caps2.surfaceCapabilities;
692 return result;
693 }
694
695 // Does the call-twice and VK_INCOMPLETE handling for querying lists
696 // of things, where we already have the full set built in a vector.
697 template <typename T>
CopyWithIncomplete(std::vector<T> const & things,T * callerPtr,uint32_t * callerCount)698 VkResult CopyWithIncomplete(std::vector<T> const& things,
699 T* callerPtr, uint32_t* callerCount) {
700 VkResult result = VK_SUCCESS;
701 if (callerPtr) {
702 if (things.size() > *callerCount)
703 result = VK_INCOMPLETE;
704 *callerCount = std::min(uint32_t(things.size()), *callerCount);
705 std::copy(things.begin(), things.begin() + *callerCount, callerPtr);
706 } else {
707 *callerCount = things.size();
708 }
709 return result;
710 }
711
712 VKAPI_ATTR
GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev,VkSurfaceKHR surface_handle,uint32_t * count,VkSurfaceFormatKHR * formats)713 VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev,
714 VkSurfaceKHR surface_handle,
715 uint32_t* count,
716 VkSurfaceFormatKHR* formats) {
717 ATRACE_CALL();
718
719 const InstanceData& instance_data = GetData(pdev);
720
721 uint64_t consumer_usage = 0;
722 bool colorspace_ext =
723 instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
724 if (surface_handle == VK_NULL_HANDLE) {
725 ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
726 bool surfaceless_enabled =
727 instance_data.hook_extensions.test(surfaceless);
728 if (!surfaceless_enabled) {
729 return VK_ERROR_SURFACE_LOST_KHR;
730 }
731 // Support for VK_GOOGLE_surfaceless_query.
732
733 // TODO(b/203826952): research proper value; temporarily use the
734 // values seen on Pixel
735 consumer_usage = AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
736 } else {
737 Surface& surface = *SurfaceFromHandle(surface_handle);
738 consumer_usage = surface.consumer_usage;
739 }
740
741 AHardwareBuffer_Desc desc = {};
742 desc.width = 1;
743 desc.height = 1;
744 desc.layers = 1;
745 desc.usage = consumer_usage | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
746 AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
747
748 // We must support R8G8B8A8
749 std::vector<VkSurfaceFormatKHR> all_formats = {
750 {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
751 {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
752 };
753
754 if (colorspace_ext) {
755 all_formats.emplace_back(VkSurfaceFormatKHR{
756 VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_PASS_THROUGH_EXT});
757 all_formats.emplace_back(VkSurfaceFormatKHR{
758 VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_PASS_THROUGH_EXT});
759 all_formats.emplace_back(VkSurfaceFormatKHR{
760 VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_BT709_LINEAR_EXT});
761 all_formats.emplace_back(VkSurfaceFormatKHR{
762 VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
763 all_formats.emplace_back(VkSurfaceFormatKHR{
764 VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
765 }
766
767 // NOTE: Any new formats that are added must be coordinated across different
768 // Android users. This includes the ANGLE team (a layered implementation of
769 // OpenGL-ES).
770
771 desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
772 if (AHardwareBuffer_isSupported(&desc)) {
773 all_formats.emplace_back(VkSurfaceFormatKHR{
774 VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
775 if (colorspace_ext) {
776 all_formats.emplace_back(
777 VkSurfaceFormatKHR{VK_FORMAT_R5G6B5_UNORM_PACK16,
778 VK_COLOR_SPACE_PASS_THROUGH_EXT});
779 }
780 }
781
782 desc.format = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
783 if (AHardwareBuffer_isSupported(&desc)) {
784 all_formats.emplace_back(VkSurfaceFormatKHR{
785 VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
786 if (colorspace_ext) {
787 all_formats.emplace_back(
788 VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
789 VK_COLOR_SPACE_PASS_THROUGH_EXT});
790 all_formats.emplace_back(
791 VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
792 VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT});
793 all_formats.emplace_back(
794 VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
795 VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT});
796 }
797 }
798
799 desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
800 if (AHardwareBuffer_isSupported(&desc)) {
801 all_formats.emplace_back(
802 VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
803 VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
804 if (colorspace_ext) {
805 all_formats.emplace_back(
806 VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
807 VK_COLOR_SPACE_PASS_THROUGH_EXT});
808 all_formats.emplace_back(
809 VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
810 VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
811 }
812 }
813
814 desc.format = AHARDWAREBUFFER_FORMAT_R8_UNORM;
815 if (AHardwareBuffer_isSupported(&desc)) {
816 if (colorspace_ext) {
817 all_formats.emplace_back(VkSurfaceFormatKHR{
818 VK_FORMAT_R8_UNORM, VK_COLOR_SPACE_PASS_THROUGH_EXT});
819 }
820 }
821
822 bool rgba10x6_formats_ext = false;
823 uint32_t exts_count;
824 const auto& driver = GetData(pdev).driver;
825 driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count,
826 nullptr);
827 std::vector<VkExtensionProperties> props(exts_count);
828 driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count,
829 props.data());
830 for (uint32_t i = 0; i < exts_count; i++) {
831 VkExtensionProperties prop = props[i];
832 if (strcmp(prop.extensionName,
833 VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME) == 0) {
834 rgba10x6_formats_ext = true;
835 }
836 }
837 desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
838 if (AHardwareBuffer_isSupported(&desc) && rgba10x6_formats_ext) {
839 all_formats.emplace_back(
840 VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
841 VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
842 if (colorspace_ext) {
843 all_formats.emplace_back(
844 VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
845 VK_COLOR_SPACE_PASS_THROUGH_EXT});
846 all_formats.emplace_back(
847 VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
848 VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
849 }
850 }
851
852 // NOTE: Any new formats that are added must be coordinated across different
853 // Android users. This includes the ANGLE team (a layered implementation of
854 // OpenGL-ES).
855
856 return CopyWithIncomplete(all_formats, formats, count);
857 }
858
859 VKAPI_ATTR
GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,VkSurfaceCapabilities2KHR * pSurfaceCapabilities)860 VkResult GetPhysicalDeviceSurfaceCapabilities2KHR(
861 VkPhysicalDevice physicalDevice,
862 const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
863 VkSurfaceCapabilities2KHR* pSurfaceCapabilities) {
864 ATRACE_CALL();
865
866 auto surface = pSurfaceInfo->surface;
867 auto capabilities = &pSurfaceCapabilities->surfaceCapabilities;
868
869 VkSurfacePresentModeEXT const *pPresentMode = nullptr;
870 for (auto pNext = reinterpret_cast<VkBaseInStructure const *>(pSurfaceInfo->pNext);
871 pNext; pNext = reinterpret_cast<VkBaseInStructure const *>(pNext->pNext)) {
872 switch (pNext->sType) {
873 case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT:
874 pPresentMode = reinterpret_cast<VkSurfacePresentModeEXT const *>(pNext);
875 break;
876
877 default:
878 break;
879 }
880 }
881
882 int err;
883 int width, height;
884 int transform_hint;
885 int max_buffer_count;
886 int min_undequeued_buffers;
887 if (surface == VK_NULL_HANDLE) {
888 const InstanceData& instance_data = GetData(physicalDevice);
889 ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
890 bool surfaceless_enabled =
891 instance_data.hook_extensions.test(surfaceless);
892 if (!surfaceless_enabled) {
893 // It is an error to pass a surface==VK_NULL_HANDLE unless the
894 // VK_GOOGLE_surfaceless_query extension is enabled
895 return VK_ERROR_SURFACE_LOST_KHR;
896 }
897 // Support for VK_GOOGLE_surfaceless_query. The primary purpose of this
898 // extension for this function is for
899 // VkSurfaceProtectedCapabilitiesKHR::supportsProtected. The following
900 // four values cannot be known without a surface. Default values will
901 // be supplied anyway, but cannot be relied upon.
902 width = 0xFFFFFFFF;
903 height = 0xFFFFFFFF;
904 transform_hint = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
905 capabilities->minImageCount = 0xFFFFFFFF;
906 capabilities->maxImageCount = 0xFFFFFFFF;
907 } else {
908 ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
909
910 err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
911 if (err != android::OK) {
912 ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
913 strerror(-err), err);
914 return VK_ERROR_SURFACE_LOST_KHR;
915 }
916 err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
917 if (err != android::OK) {
918 ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
919 strerror(-err), err);
920 return VK_ERROR_SURFACE_LOST_KHR;
921 }
922
923 err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
924 &transform_hint);
925 if (err != android::OK) {
926 ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
927 strerror(-err), err);
928 return VK_ERROR_SURFACE_LOST_KHR;
929 }
930
931 err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT,
932 &max_buffer_count);
933 if (err != android::OK) {
934 ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)",
935 strerror(-err), err);
936 return VK_ERROR_SURFACE_LOST_KHR;
937 }
938
939 err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
940 &min_undequeued_buffers);
941 if (err != android::OK) {
942 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
943 strerror(-err), err);
944 return VK_ERROR_SURFACE_LOST_KHR;
945 }
946
947 if (pPresentMode && IsSharedPresentMode(pPresentMode->presentMode)) {
948 capabilities->minImageCount = 1;
949 capabilities->maxImageCount = 1;
950 } else if (pPresentMode && pPresentMode->presentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
951 capabilities->minImageCount =
952 std::min(max_buffer_count, min_undequeued_buffers + 2);
953 capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
954 } else {
955 capabilities->minImageCount =
956 std::min(max_buffer_count, min_undequeued_buffers + 1);
957 capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
958 }
959 }
960
961 capabilities->currentExtent =
962 VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
963
964 // TODO(http://b/134182502): Figure out what the max extent should be.
965 capabilities->minImageExtent = VkExtent2D{1, 1};
966 capabilities->maxImageExtent = VkExtent2D{4096, 4096};
967
968 if (capabilities->maxImageExtent.height <
969 capabilities->currentExtent.height) {
970 capabilities->maxImageExtent.height =
971 capabilities->currentExtent.height;
972 }
973
974 if (capabilities->maxImageExtent.width <
975 capabilities->currentExtent.width) {
976 capabilities->maxImageExtent.width = capabilities->currentExtent.width;
977 }
978
979 capabilities->maxImageArrayLayers = 1;
980
981 capabilities->supportedTransforms = kSupportedTransforms;
982 capabilities->currentTransform =
983 TranslateNativeToVulkanTransform(transform_hint);
984
985 // On Android, window composition is a WindowManager property, not something
986 // associated with the bufferqueue. It can't be changed from here.
987 capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
988
989 capabilities->supportedUsageFlags =
990 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
991 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
992 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
993 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
994
995 for (auto pNext = reinterpret_cast<VkBaseOutStructure*>(pSurfaceCapabilities->pNext);
996 pNext; pNext = reinterpret_cast<VkBaseOutStructure*>(pNext->pNext)) {
997
998 switch (pNext->sType) {
999 case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR: {
1000 VkSharedPresentSurfaceCapabilitiesKHR* shared_caps =
1001 reinterpret_cast<VkSharedPresentSurfaceCapabilitiesKHR*>(pNext);
1002 // Claim same set of usage flags are supported for
1003 // shared present modes as for other modes.
1004 shared_caps->sharedPresentSupportedUsageFlags =
1005 pSurfaceCapabilities->surfaceCapabilities
1006 .supportedUsageFlags;
1007 } break;
1008
1009 case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
1010 VkSurfaceProtectedCapabilitiesKHR* protected_caps =
1011 reinterpret_cast<VkSurfaceProtectedCapabilitiesKHR*>(pNext);
1012 protected_caps->supportsProtected = VK_TRUE;
1013 } break;
1014
1015 case VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT: {
1016 VkSurfacePresentScalingCapabilitiesEXT* scaling_caps =
1017 reinterpret_cast<VkSurfacePresentScalingCapabilitiesEXT*>(pNext);
1018 // By default, Android stretches the buffer to fit the window,
1019 // without preserving aspect ratio. Other modes are technically possible
1020 // but consult with CoGS team before exposing them here!
1021 scaling_caps->supportedPresentScaling = VK_PRESENT_SCALING_STRETCH_BIT_EXT;
1022
1023 // Since we always scale, we don't support any gravity.
1024 scaling_caps->supportedPresentGravityX = 0;
1025 scaling_caps->supportedPresentGravityY = 0;
1026
1027 // Scaled image limits are just the basic image limits
1028 scaling_caps->minScaledImageExtent = capabilities->minImageExtent;
1029 scaling_caps->maxScaledImageExtent = capabilities->maxImageExtent;
1030 } break;
1031
1032 case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT: {
1033 VkSurfacePresentModeCompatibilityEXT* mode_caps =
1034 reinterpret_cast<VkSurfacePresentModeCompatibilityEXT*>(pNext);
1035
1036 ALOG_ASSERT(pPresentMode,
1037 "querying VkSurfacePresentModeCompatibilityEXT "
1038 "requires VkSurfacePresentModeEXT to be provided");
1039 std::vector<VkPresentModeKHR> compatibleModes;
1040 compatibleModes.push_back(pPresentMode->presentMode);
1041
1042 switch (pPresentMode->presentMode) {
1043 // Shared modes are both compatible with each other.
1044 case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR:
1045 compatibleModes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
1046 break;
1047 case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR:
1048 compatibleModes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR);
1049 break;
1050 default:
1051 // Other modes are only compatible with themselves.
1052 // TODO: consider whether switching between FIFO and MAILBOX is reasonable
1053 break;
1054 }
1055
1056 // Note: this does not generate VK_INCOMPLETE since we're nested inside
1057 // a larger query and there would be no way to determine exactly where it came from.
1058 CopyWithIncomplete(compatibleModes, mode_caps->pPresentModes,
1059 &mode_caps->presentModeCount);
1060 } break;
1061
1062 default:
1063 // Ignore all other extension structs
1064 break;
1065 }
1066 }
1067
1068 return VK_SUCCESS;
1069 }
1070
1071 VKAPI_ATTR
GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,uint32_t * pSurfaceFormatCount,VkSurfaceFormat2KHR * pSurfaceFormats)1072 VkResult GetPhysicalDeviceSurfaceFormats2KHR(
1073 VkPhysicalDevice physicalDevice,
1074 const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
1075 uint32_t* pSurfaceFormatCount,
1076 VkSurfaceFormat2KHR* pSurfaceFormats) {
1077 ATRACE_CALL();
1078
1079 if (!pSurfaceFormats) {
1080 return GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice,
1081 pSurfaceInfo->surface,
1082 pSurfaceFormatCount, nullptr);
1083 }
1084
1085 // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
1086 // after the call.
1087 std::vector<VkSurfaceFormatKHR> surface_formats(*pSurfaceFormatCount);
1088 VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
1089 physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
1090 surface_formats.data());
1091
1092 if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
1093 return result;
1094 }
1095
1096 const auto& driver = GetData(physicalDevice).driver;
1097
1098 // marshal results individually due to stride difference.
1099 uint32_t formats_to_marshal = *pSurfaceFormatCount;
1100 for (uint32_t i = 0u; i < formats_to_marshal; i++) {
1101 pSurfaceFormats[i].surfaceFormat = surface_formats[i];
1102
1103 // Query the compression properties for the surface format
1104 VkSurfaceFormat2KHR* pSurfaceFormat = &pSurfaceFormats[i];
1105 while (pSurfaceFormat->pNext) {
1106 pSurfaceFormat =
1107 reinterpret_cast<VkSurfaceFormat2KHR*>(pSurfaceFormat->pNext);
1108 switch (pSurfaceFormat->sType) {
1109 case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT: {
1110 VkImageCompressionPropertiesEXT* surfaceCompressionProps =
1111 reinterpret_cast<VkImageCompressionPropertiesEXT*>(
1112 pSurfaceFormat);
1113
1114 if (surfaceCompressionProps &&
1115 driver.GetPhysicalDeviceImageFormatProperties2KHR) {
1116 VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {};
1117 imageFormatInfo.sType =
1118 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
1119 imageFormatInfo.format =
1120 pSurfaceFormats[i].surfaceFormat.format;
1121 imageFormatInfo.type = VK_IMAGE_TYPE_2D;
1122 imageFormatInfo.usage =
1123 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1124 imageFormatInfo.pNext = nullptr;
1125
1126 VkImageCompressionControlEXT compressionControl = {};
1127 compressionControl.sType =
1128 VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
1129 compressionControl.pNext = imageFormatInfo.pNext;
1130 compressionControl.flags =
1131 VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
1132
1133 imageFormatInfo.pNext = &compressionControl;
1134
1135 VkImageCompressionPropertiesEXT compressionProps = {};
1136 compressionProps.sType =
1137 VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT;
1138 compressionProps.pNext = nullptr;
1139
1140 VkImageFormatProperties2KHR imageFormatProps = {};
1141 imageFormatProps.sType =
1142 VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
1143 imageFormatProps.pNext = &compressionProps;
1144
1145 VkResult compressionRes =
1146 driver.GetPhysicalDeviceImageFormatProperties2KHR(
1147 physicalDevice, &imageFormatInfo,
1148 &imageFormatProps);
1149 if (compressionRes == VK_SUCCESS) {
1150 surfaceCompressionProps->imageCompressionFlags =
1151 compressionProps.imageCompressionFlags;
1152 surfaceCompressionProps
1153 ->imageCompressionFixedRateFlags =
1154 compressionProps.imageCompressionFixedRateFlags;
1155 } else {
1156 return compressionRes;
1157 }
1158 }
1159 } break;
1160
1161 default:
1162 // Ignore all other extension structs
1163 break;
1164 }
1165 }
1166 }
1167
1168 return result;
1169 }
1170
1171 VKAPI_ATTR
GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev,VkSurfaceKHR surface,uint32_t * count,VkPresentModeKHR * modes)1172 VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev,
1173 VkSurfaceKHR surface,
1174 uint32_t* count,
1175 VkPresentModeKHR* modes) {
1176 ATRACE_CALL();
1177
1178 int err;
1179 int query_value;
1180 std::vector<VkPresentModeKHR> present_modes;
1181 if (surface == VK_NULL_HANDLE) {
1182 const InstanceData& instance_data = GetData(pdev);
1183 ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
1184 bool surfaceless_enabled =
1185 instance_data.hook_extensions.test(surfaceless);
1186 if (!surfaceless_enabled) {
1187 return VK_ERROR_SURFACE_LOST_KHR;
1188 }
1189 // Support for VK_GOOGLE_surfaceless_query. The primary purpose of this
1190 // extension for this function is for
1191 // VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR and
1192 // VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR. We technically cannot
1193 // know if VK_PRESENT_MODE_SHARED_MAILBOX_KHR is supported without a
1194 // surface, and that cannot be relied upon. Therefore, don't return it.
1195 present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
1196 } else {
1197 ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
1198
1199 err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1200 &query_value);
1201 if (err != android::OK || query_value < 0) {
1202 ALOGE(
1203 "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
1204 "value=%d",
1205 strerror(-err), err, query_value);
1206 return VK_ERROR_SURFACE_LOST_KHR;
1207 }
1208 uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
1209
1210 err =
1211 window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
1212 if (err != android::OK || query_value < 0) {
1213 ALOGE(
1214 "NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d",
1215 strerror(-err), err, query_value);
1216 return VK_ERROR_SURFACE_LOST_KHR;
1217 }
1218 uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
1219
1220 if (min_undequeued_buffers + 1 < max_buffer_count)
1221 present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
1222 present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
1223 }
1224
1225 VkPhysicalDevicePresentationPropertiesANDROID present_properties;
1226 QueryPresentationProperties(pdev, &present_properties);
1227 if (present_properties.sharedImage) {
1228 present_modes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR);
1229 present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
1230 }
1231
1232 return CopyWithIncomplete(present_modes, modes, count);
1233 }
1234
1235 VKAPI_ATTR
GetDeviceGroupPresentCapabilitiesKHR(VkDevice,VkDeviceGroupPresentCapabilitiesKHR * pDeviceGroupPresentCapabilities)1236 VkResult GetDeviceGroupPresentCapabilitiesKHR(
1237 VkDevice,
1238 VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
1239 ATRACE_CALL();
1240
1241 ALOGV_IF(pDeviceGroupPresentCapabilities->sType !=
1242 VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR,
1243 "vkGetDeviceGroupPresentCapabilitiesKHR: invalid "
1244 "VkDeviceGroupPresentCapabilitiesKHR structure type %d",
1245 pDeviceGroupPresentCapabilities->sType);
1246
1247 memset(pDeviceGroupPresentCapabilities->presentMask, 0,
1248 sizeof(pDeviceGroupPresentCapabilities->presentMask));
1249
1250 // assume device group of size 1
1251 pDeviceGroupPresentCapabilities->presentMask[0] = 1 << 0;
1252 pDeviceGroupPresentCapabilities->modes =
1253 VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1254
1255 return VK_SUCCESS;
1256 }
1257
1258 VKAPI_ATTR
GetDeviceGroupSurfacePresentModesKHR(VkDevice,VkSurfaceKHR,VkDeviceGroupPresentModeFlagsKHR * pModes)1259 VkResult GetDeviceGroupSurfacePresentModesKHR(
1260 VkDevice,
1261 VkSurfaceKHR,
1262 VkDeviceGroupPresentModeFlagsKHR* pModes) {
1263 ATRACE_CALL();
1264
1265 *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1266 return VK_SUCCESS;
1267 }
1268
1269 VKAPI_ATTR
GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice,VkSurfaceKHR surface,uint32_t * pRectCount,VkRect2D * pRects)1270 VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice,
1271 VkSurfaceKHR surface,
1272 uint32_t* pRectCount,
1273 VkRect2D* pRects) {
1274 ATRACE_CALL();
1275
1276 if (!pRects) {
1277 *pRectCount = 1;
1278 } else {
1279 uint32_t count = std::min(*pRectCount, 1u);
1280 bool incomplete = *pRectCount < 1;
1281
1282 *pRectCount = count;
1283
1284 if (incomplete) {
1285 return VK_INCOMPLETE;
1286 }
1287
1288 int err;
1289 ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
1290
1291 int width = 0, height = 0;
1292 err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
1293 if (err != android::OK) {
1294 ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
1295 strerror(-err), err);
1296 }
1297 err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
1298 if (err != android::OK) {
1299 ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
1300 strerror(-err), err);
1301 }
1302
1303 pRects[0].offset.x = 0;
1304 pRects[0].offset.y = 0;
1305 pRects[0].extent = VkExtent2D{static_cast<uint32_t>(width),
1306 static_cast<uint32_t>(height)};
1307 }
1308 return VK_SUCCESS;
1309 }
1310
DestroySwapchainInternal(VkDevice device,VkSwapchainKHR swapchain_handle,const VkAllocationCallbacks * allocator)1311 static void DestroySwapchainInternal(VkDevice device,
1312 VkSwapchainKHR swapchain_handle,
1313 const VkAllocationCallbacks* allocator) {
1314 ATRACE_CALL();
1315
1316 const auto& dispatch = GetData(device).driver;
1317 Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
1318 if (!swapchain) {
1319 return;
1320 }
1321
1322 bool active = swapchain->surface.swapchain_handle == swapchain_handle;
1323 ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
1324
1325 if (window && swapchain->frame_timestamps_enabled) {
1326 native_window_enable_frame_timestamps(window, false);
1327 }
1328
1329 for (uint32_t i = 0; i < swapchain->num_images; i++) {
1330 ReleaseSwapchainImage(device, swapchain->shared, window, -1,
1331 swapchain->images[i], false);
1332 }
1333
1334 if (active) {
1335 swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
1336 }
1337
1338 if (!allocator) {
1339 allocator = &GetData(device).allocator;
1340 }
1341
1342 swapchain->~Swapchain();
1343 allocator->pfnFree(allocator->pUserData, swapchain);
1344 }
1345
1346 VKAPI_ATTR
CreateSwapchainKHR(VkDevice device,const VkSwapchainCreateInfoKHR * create_info,const VkAllocationCallbacks * allocator,VkSwapchainKHR * swapchain_handle)1347 VkResult CreateSwapchainKHR(VkDevice device,
1348 const VkSwapchainCreateInfoKHR* create_info,
1349 const VkAllocationCallbacks* allocator,
1350 VkSwapchainKHR* swapchain_handle) {
1351 ATRACE_CALL();
1352
1353 int err;
1354 VkResult result = VK_SUCCESS;
1355
1356 ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
1357 " minImageCount=%u imageFormat=%u imageColorSpace=%u"
1358 " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
1359 " oldSwapchain=0x%" PRIx64,
1360 reinterpret_cast<uint64_t>(create_info->surface),
1361 create_info->minImageCount, create_info->imageFormat,
1362 create_info->imageColorSpace, create_info->imageExtent.width,
1363 create_info->imageExtent.height, create_info->imageUsage,
1364 create_info->preTransform, create_info->presentMode,
1365 reinterpret_cast<uint64_t>(create_info->oldSwapchain));
1366
1367 if (!allocator)
1368 allocator = &GetData(device).allocator;
1369
1370 android::PixelFormat native_pixel_format =
1371 GetNativePixelFormat(create_info->imageFormat);
1372 android_dataspace native_dataspace =
1373 GetNativeDataspace(create_info->imageColorSpace, native_pixel_format);
1374 if (native_dataspace == HAL_DATASPACE_UNKNOWN) {
1375 ALOGE(
1376 "CreateSwapchainKHR(VkSwapchainCreateInfoKHR.imageColorSpace = %d) "
1377 "failed: Unsupported color space",
1378 create_info->imageColorSpace);
1379 return VK_ERROR_INITIALIZATION_FAILED;
1380 }
1381
1382 ALOGV_IF(create_info->imageArrayLayers != 1,
1383 "swapchain imageArrayLayers=%u not supported",
1384 create_info->imageArrayLayers);
1385 ALOGV_IF((create_info->preTransform & ~kSupportedTransforms) != 0,
1386 "swapchain preTransform=%#x not supported",
1387 create_info->preTransform);
1388 ALOGV_IF(!(create_info->presentMode == VK_PRESENT_MODE_FIFO_KHR ||
1389 create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ||
1390 create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
1391 create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR),
1392 "swapchain presentMode=%u not supported",
1393 create_info->presentMode);
1394
1395 Surface& surface = *SurfaceFromHandle(create_info->surface);
1396
1397 if (surface.swapchain_handle != create_info->oldSwapchain) {
1398 ALOGV("Can't create a swapchain for VkSurfaceKHR 0x%" PRIx64
1399 " because it already has active swapchain 0x%" PRIx64
1400 " but VkSwapchainCreateInfo::oldSwapchain=0x%" PRIx64,
1401 reinterpret_cast<uint64_t>(create_info->surface),
1402 reinterpret_cast<uint64_t>(surface.swapchain_handle),
1403 reinterpret_cast<uint64_t>(create_info->oldSwapchain));
1404 return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
1405 }
1406 if (create_info->oldSwapchain != VK_NULL_HANDLE)
1407 OrphanSwapchain(device, SwapchainFromHandle(create_info->oldSwapchain));
1408
1409 // -- Reset the native window --
1410 // The native window might have been used previously, and had its properties
1411 // changed from defaults. That will affect the answer we get for queries
1412 // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we
1413 // attempt such queries.
1414
1415 // The native window only allows dequeueing all buffers before any have
1416 // been queued, since after that point at least one is assumed to be in
1417 // non-FREE state at any given time. Disconnecting and re-connecting
1418 // orphans the previous buffers, getting us back to the state where we can
1419 // dequeue all buffers.
1420 //
1421 // This is not necessary if the surface was never used previously.
1422 //
1423 // TODO(http://b/134186185) recycle swapchain images more efficiently
1424 ANativeWindow* window = surface.window.get();
1425 if (surface.used_by_swapchain) {
1426 err = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
1427 ALOGW_IF(err != android::OK,
1428 "native_window_api_disconnect failed: %s (%d)", strerror(-err),
1429 err);
1430 err = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
1431 ALOGW_IF(err != android::OK,
1432 "native_window_api_connect failed: %s (%d)", strerror(-err),
1433 err);
1434 }
1435
1436 err =
1437 window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, nsecs_t{-1});
1438 if (err != android::OK) {
1439 ALOGE("window->perform(SET_DEQUEUE_TIMEOUT) failed: %s (%d)",
1440 strerror(-err), err);
1441 return VK_ERROR_SURFACE_LOST_KHR;
1442 }
1443
1444 int swap_interval =
1445 create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
1446 err = window->setSwapInterval(window, swap_interval);
1447 if (err != android::OK) {
1448 ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
1449 strerror(-err), err);
1450 return VK_ERROR_SURFACE_LOST_KHR;
1451 }
1452
1453 err = native_window_set_shared_buffer_mode(window, false);
1454 if (err != android::OK) {
1455 ALOGE("native_window_set_shared_buffer_mode(false) failed: %s (%d)",
1456 strerror(-err), err);
1457 return VK_ERROR_SURFACE_LOST_KHR;
1458 }
1459
1460 err = native_window_set_auto_refresh(window, false);
1461 if (err != android::OK) {
1462 ALOGE("native_window_set_auto_refresh(false) failed: %s (%d)",
1463 strerror(-err), err);
1464 return VK_ERROR_SURFACE_LOST_KHR;
1465 }
1466
1467 // -- Configure the native window --
1468
1469 const auto& dispatch = GetData(device).driver;
1470
1471 err = native_window_set_buffers_format(window, native_pixel_format);
1472 if (err != android::OK) {
1473 ALOGE("native_window_set_buffers_format(%s) failed: %s (%d)",
1474 decodePixelFormat(native_pixel_format).c_str(), strerror(-err), err);
1475 return VK_ERROR_SURFACE_LOST_KHR;
1476 }
1477
1478 /* Respect consumer default dataspace upon HAL_DATASPACE_ARBITRARY. */
1479 if (native_dataspace != HAL_DATASPACE_ARBITRARY) {
1480 err = native_window_set_buffers_data_space(window, native_dataspace);
1481 if (err != android::OK) {
1482 ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
1483 native_dataspace, strerror(-err), err);
1484 return VK_ERROR_SURFACE_LOST_KHR;
1485 }
1486 }
1487
1488 err = native_window_set_buffers_dimensions(
1489 window, static_cast<int>(create_info->imageExtent.width),
1490 static_cast<int>(create_info->imageExtent.height));
1491 if (err != android::OK) {
1492 ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
1493 create_info->imageExtent.width, create_info->imageExtent.height,
1494 strerror(-err), err);
1495 return VK_ERROR_SURFACE_LOST_KHR;
1496 }
1497
1498 // VkSwapchainCreateInfo::preTransform indicates the transformation the app
1499 // applied during rendering. native_window_set_transform() expects the
1500 // inverse: the transform the app is requesting that the compositor perform
1501 // during composition. With native windows, pre-transform works by rendering
1502 // with the same transform the compositor is applying (as in Vulkan), but
1503 // then requesting the inverse transform, so that when the compositor does
1504 // it's job the two transforms cancel each other out and the compositor ends
1505 // up applying an identity transform to the app's buffer.
1506 err = native_window_set_buffers_transform(
1507 window, InvertTransformToNative(create_info->preTransform));
1508 if (err != android::OK) {
1509 ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
1510 InvertTransformToNative(create_info->preTransform),
1511 strerror(-err), err);
1512 return VK_ERROR_SURFACE_LOST_KHR;
1513 }
1514
1515 err = native_window_set_scaling_mode(
1516 window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
1517 if (err != android::OK) {
1518 ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
1519 strerror(-err), err);
1520 return VK_ERROR_SURFACE_LOST_KHR;
1521 }
1522
1523 VkSwapchainImageUsageFlagsANDROID swapchain_image_usage = 0;
1524 if (IsSharedPresentMode(create_info->presentMode)) {
1525 swapchain_image_usage |= VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID;
1526 err = native_window_set_shared_buffer_mode(window, true);
1527 if (err != android::OK) {
1528 ALOGE("native_window_set_shared_buffer_mode failed: %s (%d)", strerror(-err), err);
1529 return VK_ERROR_SURFACE_LOST_KHR;
1530 }
1531 }
1532
1533 if (create_info->presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
1534 err = native_window_set_auto_refresh(window, true);
1535 if (err != android::OK) {
1536 ALOGE("native_window_set_auto_refresh failed: %s (%d)", strerror(-err), err);
1537 return VK_ERROR_SURFACE_LOST_KHR;
1538 }
1539 }
1540
1541 int query_value;
1542 err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1543 &query_value);
1544 if (err != android::OK || query_value < 0) {
1545 ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
1546 query_value);
1547 return VK_ERROR_SURFACE_LOST_KHR;
1548 }
1549 uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
1550 const auto mailbox_num_images = std::max(3u, create_info->minImageCount);
1551 const auto requested_images =
1552 swap_interval ? create_info->minImageCount : mailbox_num_images;
1553 uint32_t num_images = requested_images - 1 + min_undequeued_buffers;
1554
1555 // Lower layer insists that we have at least min_undequeued_buffers + 1
1556 // buffers. This is wasteful and we'd like to relax it in the shared case,
1557 // but not all the pieces are in place for that to work yet. Note we only
1558 // lie to the lower layer--we don't want to give the app back a swapchain
1559 // with extra images (which they can't actually use!).
1560 uint32_t min_buffer_count = min_undequeued_buffers + 1;
1561 err = native_window_set_buffer_count(
1562 window, std::max(min_buffer_count, num_images));
1563 if (err != android::OK) {
1564 ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
1565 strerror(-err), err);
1566 return VK_ERROR_SURFACE_LOST_KHR;
1567 }
1568
1569 // In shared mode the num_images must be one regardless of how many
1570 // buffers were allocated for the buffer queue.
1571 if (swapchain_image_usage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID) {
1572 num_images = 1;
1573 }
1574
1575 void* usage_info_pNext = nullptr;
1576 VkImageCompressionControlEXT image_compression = {};
1577 uint64_t native_usage = 0;
1578 if (dispatch.GetSwapchainGrallocUsage4ANDROID) {
1579 ATRACE_BEGIN("GetSwapchainGrallocUsage4ANDROID");
1580 VkGrallocUsageInfo2ANDROID gralloc_usage_info = {};
1581 gralloc_usage_info.sType =
1582 VK_STRUCTURE_TYPE_GRALLOC_USAGE_INFO_2_ANDROID;
1583 gralloc_usage_info.format = create_info->imageFormat;
1584 gralloc_usage_info.imageUsage = create_info->imageUsage;
1585 gralloc_usage_info.swapchainImageUsage = swapchain_image_usage;
1586
1587 // Look through the pNext chain for an image compression control struct
1588 // if one is found AND the appropriate extensions are enabled,
1589 // append it to be the gralloc usage pNext chain
1590 const VkSwapchainCreateInfoKHR* create_infos = create_info;
1591 while (create_infos->pNext) {
1592 create_infos = reinterpret_cast<const VkSwapchainCreateInfoKHR*>(
1593 create_infos->pNext);
1594 switch (create_infos->sType) {
1595 case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: {
1596 const VkImageCompressionControlEXT* compression_infos =
1597 reinterpret_cast<const VkImageCompressionControlEXT*>(
1598 create_infos);
1599 image_compression = *compression_infos;
1600 image_compression.pNext = nullptr;
1601 usage_info_pNext = &image_compression;
1602 } break;
1603
1604 default:
1605 // Ignore all other info structs
1606 break;
1607 }
1608 }
1609 gralloc_usage_info.pNext = usage_info_pNext;
1610
1611 result = dispatch.GetSwapchainGrallocUsage4ANDROID(
1612 device, &gralloc_usage_info, &native_usage);
1613 ATRACE_END();
1614 if (result != VK_SUCCESS) {
1615 ALOGE("vkGetSwapchainGrallocUsage4ANDROID failed: %d", result);
1616 return VK_ERROR_SURFACE_LOST_KHR;
1617 }
1618 } else if (dispatch.GetSwapchainGrallocUsage3ANDROID) {
1619 ATRACE_BEGIN("GetSwapchainGrallocUsage3ANDROID");
1620 VkGrallocUsageInfoANDROID gralloc_usage_info = {};
1621 gralloc_usage_info.sType = VK_STRUCTURE_TYPE_GRALLOC_USAGE_INFO_ANDROID;
1622 gralloc_usage_info.format = create_info->imageFormat;
1623 gralloc_usage_info.imageUsage = create_info->imageUsage;
1624
1625 // Look through the pNext chain for an image compression control struct
1626 // if one is found AND the appropriate extensions are enabled,
1627 // append it to be the gralloc usage pNext chain
1628 const VkSwapchainCreateInfoKHR* create_infos = create_info;
1629 while (create_infos->pNext) {
1630 create_infos = reinterpret_cast<const VkSwapchainCreateInfoKHR*>(
1631 create_infos->pNext);
1632 switch (create_infos->sType) {
1633 case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: {
1634 const VkImageCompressionControlEXT* compression_infos =
1635 reinterpret_cast<const VkImageCompressionControlEXT*>(
1636 create_infos);
1637 image_compression = *compression_infos;
1638 image_compression.pNext = nullptr;
1639 usage_info_pNext = &image_compression;
1640 } break;
1641
1642 default:
1643 // Ignore all other info structs
1644 break;
1645 }
1646 }
1647 gralloc_usage_info.pNext = usage_info_pNext;
1648
1649 result = dispatch.GetSwapchainGrallocUsage3ANDROID(
1650 device, &gralloc_usage_info, &native_usage);
1651 ATRACE_END();
1652 if (result != VK_SUCCESS) {
1653 ALOGE("vkGetSwapchainGrallocUsage3ANDROID failed: %d", result);
1654 return VK_ERROR_SURFACE_LOST_KHR;
1655 }
1656 } else if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
1657 uint64_t consumer_usage, producer_usage;
1658 ATRACE_BEGIN("GetSwapchainGrallocUsage2ANDROID");
1659 result = dispatch.GetSwapchainGrallocUsage2ANDROID(
1660 device, create_info->imageFormat, create_info->imageUsage,
1661 swapchain_image_usage, &consumer_usage, &producer_usage);
1662 ATRACE_END();
1663 if (result != VK_SUCCESS) {
1664 ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
1665 return VK_ERROR_SURFACE_LOST_KHR;
1666 }
1667 native_usage =
1668 convertGralloc1ToBufferUsage(producer_usage, consumer_usage);
1669 } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
1670 ATRACE_BEGIN("GetSwapchainGrallocUsageANDROID");
1671 int32_t legacy_usage = 0;
1672 result = dispatch.GetSwapchainGrallocUsageANDROID(
1673 device, create_info->imageFormat, create_info->imageUsage,
1674 &legacy_usage);
1675 ATRACE_END();
1676 if (result != VK_SUCCESS) {
1677 ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
1678 return VK_ERROR_SURFACE_LOST_KHR;
1679 }
1680 native_usage = static_cast<uint64_t>(legacy_usage);
1681 }
1682 native_usage |= surface.consumer_usage;
1683
1684 bool createProtectedSwapchain = false;
1685 if (create_info->flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR) {
1686 createProtectedSwapchain = true;
1687 native_usage |= BufferUsage::PROTECTED;
1688 }
1689 err = native_window_set_usage(window, native_usage);
1690 if (err != android::OK) {
1691 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
1692 return VK_ERROR_SURFACE_LOST_KHR;
1693 }
1694
1695 int transform_hint;
1696 err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
1697 if (err != android::OK) {
1698 ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
1699 strerror(-err), err);
1700 return VK_ERROR_SURFACE_LOST_KHR;
1701 }
1702
1703 int64_t refresh_duration;
1704 err = native_window_get_refresh_cycle_duration(window, &refresh_duration);
1705 if (err != android::OK) {
1706 ALOGE("native_window_get_refresh_cycle_duration query failed: %s (%d)",
1707 strerror(-err), err);
1708 return VK_ERROR_SURFACE_LOST_KHR;
1709 }
1710 // -- Allocate our Swapchain object --
1711 // After this point, we must deallocate the swapchain on error.
1712
1713 void* mem = allocator->pfnAllocation(allocator->pUserData,
1714 sizeof(Swapchain), alignof(Swapchain),
1715 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1716 if (!mem)
1717 return VK_ERROR_OUT_OF_HOST_MEMORY;
1718 Swapchain* swapchain = new (mem)
1719 Swapchain(surface, num_images, create_info->presentMode,
1720 TranslateVulkanToNativeTransform(create_info->preTransform),
1721 refresh_duration);
1722 VkSwapchainImageCreateInfoANDROID swapchain_image_create = {
1723 #pragma clang diagnostic push
1724 #pragma clang diagnostic ignored "-Wold-style-cast"
1725 .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID,
1726 #pragma clang diagnostic pop
1727 .pNext = usage_info_pNext,
1728 .usage = swapchain_image_usage,
1729 };
1730 VkNativeBufferANDROID image_native_buffer = {
1731 #pragma clang diagnostic push
1732 #pragma clang diagnostic ignored "-Wold-style-cast"
1733 .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
1734 #pragma clang diagnostic pop
1735 .pNext = &swapchain_image_create,
1736 };
1737
1738 VkImageCreateInfo image_create = {
1739 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1740 .pNext = nullptr,
1741 .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
1742 .imageType = VK_IMAGE_TYPE_2D,
1743 .format = create_info->imageFormat,
1744 .extent = {
1745 create_info->imageExtent.width,
1746 create_info->imageExtent.height,
1747 1
1748 },
1749 .mipLevels = 1,
1750 .arrayLayers = 1,
1751 .samples = VK_SAMPLE_COUNT_1_BIT,
1752 .tiling = VK_IMAGE_TILING_OPTIMAL,
1753 .usage = create_info->imageUsage,
1754 .sharingMode = create_info->imageSharingMode,
1755 .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
1756 .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
1757 };
1758
1759 // Note: don't do deferred allocation for shared present modes. There's only one buffer
1760 // involved so very little benefit.
1761 if ((create_info->flags & VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT) &&
1762 !IsSharedPresentMode(create_info->presentMode)) {
1763 // Don't want to touch the underlying gralloc buffers yet;
1764 // instead just create unbound VkImages which will later be bound to memory inside
1765 // AcquireNextImage.
1766 VkImageSwapchainCreateInfoKHR image_swapchain_create = {
1767 .sType = VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR,
1768 .pNext = nullptr,
1769 .swapchain = HandleFromSwapchain(swapchain),
1770 };
1771 image_create.pNext = &image_swapchain_create;
1772
1773 for (uint32_t i = 0; i < num_images; i++) {
1774 Swapchain::Image& img = swapchain->images[i];
1775 img.buffer = nullptr;
1776 img.dequeued = false;
1777
1778 result = dispatch.CreateImage(device, &image_create, nullptr, &img.image);
1779 if (result != VK_SUCCESS) {
1780 ALOGD("vkCreateImage w/ for deferred swapchain image failed: %u", result);
1781 break;
1782 }
1783 }
1784 } else {
1785 // -- Dequeue all buffers and create a VkImage for each --
1786 // Any failures during or after this must cancel the dequeued buffers.
1787
1788 for (uint32_t i = 0; i < num_images; i++) {
1789 Swapchain::Image& img = swapchain->images[i];
1790
1791 ANativeWindowBuffer* buffer;
1792 err = window->dequeueBuffer(window, &buffer, &img.dequeue_fence);
1793 if (err != android::OK) {
1794 ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
1795 switch (-err) {
1796 case ENOMEM:
1797 result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
1798 break;
1799 default:
1800 result = VK_ERROR_SURFACE_LOST_KHR;
1801 break;
1802 }
1803 break;
1804 }
1805 img.buffer = buffer;
1806 img.dequeued = true;
1807
1808 image_native_buffer.handle = img.buffer->handle;
1809 image_native_buffer.stride = img.buffer->stride;
1810 image_native_buffer.format = img.buffer->format;
1811 image_native_buffer.usage = int(img.buffer->usage);
1812 android_convertGralloc0To1Usage(int(img.buffer->usage),
1813 &image_native_buffer.usage2.producer,
1814 &image_native_buffer.usage2.consumer);
1815 image_native_buffer.usage3 = img.buffer->usage;
1816 image_create.pNext = &image_native_buffer;
1817
1818 ATRACE_BEGIN("CreateImage");
1819 result =
1820 dispatch.CreateImage(device, &image_create, nullptr, &img.image);
1821 ATRACE_END();
1822 if (result != VK_SUCCESS) {
1823 ALOGD("vkCreateImage w/ native buffer failed: %u", result);
1824 break;
1825 }
1826 }
1827
1828 // -- Cancel all buffers, returning them to the queue --
1829 // If an error occurred before, also destroy the VkImage and release the
1830 // buffer reference. Otherwise, we retain a strong reference to the buffer.
1831 for (uint32_t i = 0; i < num_images; i++) {
1832 Swapchain::Image& img = swapchain->images[i];
1833 if (img.dequeued) {
1834 if (!swapchain->shared) {
1835 window->cancelBuffer(window, img.buffer.get(),
1836 img.dequeue_fence);
1837 img.dequeue_fence = -1;
1838 img.dequeued = false;
1839 }
1840 }
1841 }
1842 }
1843
1844 if (result != VK_SUCCESS) {
1845 DestroySwapchainInternal(device, HandleFromSwapchain(swapchain),
1846 allocator);
1847 return result;
1848 }
1849
1850 if (transform_hint != swapchain->pre_transform) {
1851 // Log that the app is not doing pre-rotation.
1852 android::GraphicsEnv::getInstance().setTargetStats(
1853 android::GpuStatsInfo::Stats::FALSE_PREROTATION);
1854 }
1855
1856 // Set stats for creating a Vulkan swapchain
1857 android::GraphicsEnv::getInstance().setTargetStats(
1858 android::GpuStatsInfo::Stats::CREATED_VULKAN_SWAPCHAIN);
1859
1860 surface.used_by_swapchain = true;
1861 surface.swapchain_handle = HandleFromSwapchain(swapchain);
1862 *swapchain_handle = surface.swapchain_handle;
1863 return VK_SUCCESS;
1864 }
1865
1866 VKAPI_ATTR
DestroySwapchainKHR(VkDevice device,VkSwapchainKHR swapchain_handle,const VkAllocationCallbacks * allocator)1867 void DestroySwapchainKHR(VkDevice device,
1868 VkSwapchainKHR swapchain_handle,
1869 const VkAllocationCallbacks* allocator) {
1870 ATRACE_CALL();
1871
1872 DestroySwapchainInternal(device, swapchain_handle, allocator);
1873 }
1874
1875 VKAPI_ATTR
GetSwapchainImagesKHR(VkDevice,VkSwapchainKHR swapchain_handle,uint32_t * count,VkImage * images)1876 VkResult GetSwapchainImagesKHR(VkDevice,
1877 VkSwapchainKHR swapchain_handle,
1878 uint32_t* count,
1879 VkImage* images) {
1880 ATRACE_CALL();
1881
1882 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
1883 ALOGW_IF(swapchain.surface.swapchain_handle != swapchain_handle,
1884 "getting images for non-active swapchain 0x%" PRIx64
1885 "; only dequeued image handles are valid",
1886 reinterpret_cast<uint64_t>(swapchain_handle));
1887 VkResult result = VK_SUCCESS;
1888 if (images) {
1889 uint32_t n = swapchain.num_images;
1890 if (*count < swapchain.num_images) {
1891 n = *count;
1892 result = VK_INCOMPLETE;
1893 }
1894 for (uint32_t i = 0; i < n; i++)
1895 images[i] = swapchain.images[i].image;
1896 *count = n;
1897 } else {
1898 *count = swapchain.num_images;
1899 }
1900 return result;
1901 }
1902
1903 VKAPI_ATTR
AcquireNextImageKHR(VkDevice device,VkSwapchainKHR swapchain_handle,uint64_t timeout,VkSemaphore semaphore,VkFence vk_fence,uint32_t * image_index)1904 VkResult AcquireNextImageKHR(VkDevice device,
1905 VkSwapchainKHR swapchain_handle,
1906 uint64_t timeout,
1907 VkSemaphore semaphore,
1908 VkFence vk_fence,
1909 uint32_t* image_index) {
1910 ATRACE_CALL();
1911
1912 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
1913 ANativeWindow* window = swapchain.surface.window.get();
1914 VkResult result;
1915 int err;
1916
1917 if (swapchain.surface.swapchain_handle != swapchain_handle)
1918 return VK_ERROR_OUT_OF_DATE_KHR;
1919
1920 if (swapchain.shared) {
1921 // In shared mode, we keep the buffer dequeued all the time, so we don't
1922 // want to dequeue a buffer here. Instead, just ask the driver to ensure
1923 // the semaphore and fence passed to us will be signalled.
1924 *image_index = 0;
1925 result = GetData(device).driver.AcquireImageANDROID(
1926 device, swapchain.images[*image_index].image, -1, semaphore, vk_fence);
1927 return result;
1928 }
1929
1930 const nsecs_t acquire_next_image_timeout =
1931 timeout > (uint64_t)std::numeric_limits<nsecs_t>::max() ? -1 : timeout;
1932 if (acquire_next_image_timeout != swapchain.acquire_next_image_timeout) {
1933 // Cache the timeout to avoid the duplicate binder cost.
1934 err = window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT,
1935 acquire_next_image_timeout);
1936 if (err != android::OK) {
1937 ALOGE("window->perform(SET_DEQUEUE_TIMEOUT) failed: %s (%d)",
1938 strerror(-err), err);
1939 return VK_ERROR_SURFACE_LOST_KHR;
1940 }
1941 swapchain.acquire_next_image_timeout = acquire_next_image_timeout;
1942 }
1943
1944 ANativeWindowBuffer* buffer;
1945 int fence_fd;
1946 err = window->dequeueBuffer(window, &buffer, &fence_fd);
1947 if (err == android::TIMED_OUT || err == android::INVALID_OPERATION) {
1948 ALOGW("dequeueBuffer timed out: %s (%d)", strerror(-err), err);
1949 return timeout ? VK_TIMEOUT : VK_NOT_READY;
1950 } else if (err != android::OK) {
1951 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
1952 return VK_ERROR_SURFACE_LOST_KHR;
1953 }
1954
1955 uint32_t idx;
1956 for (idx = 0; idx < swapchain.num_images; idx++) {
1957 if (swapchain.images[idx].buffer.get() == buffer) {
1958 swapchain.images[idx].dequeued = true;
1959 swapchain.images[idx].dequeue_fence = fence_fd;
1960 break;
1961 }
1962 }
1963
1964 // If this is a deferred alloc swapchain, this may be the first time we've
1965 // seen a particular buffer. If so, there should be an empty slot. Find it,
1966 // and bind the gralloc buffer to the VkImage for that slot. If there is no
1967 // empty slot, then we dequeued an unexpected buffer. Non-deferred swapchains
1968 // will also take this path, but will never have an empty slot since we
1969 // populated them all upfront.
1970 if (idx == swapchain.num_images) {
1971 for (idx = 0; idx < swapchain.num_images; idx++) {
1972 if (!swapchain.images[idx].buffer) {
1973 // Note: this structure is technically required for
1974 // Vulkan correctness, even though the driver is probably going
1975 // to use everything from the VkNativeBufferANDROID below.
1976 // This is kindof silly, but it's how we did the ANB
1977 // side of VK_KHR_swapchain v69, so we're stuck with it unless
1978 // we want to go tinkering with the ANB spec some more.
1979 VkBindImageMemorySwapchainInfoKHR bimsi = {
1980 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR,
1981 .pNext = nullptr,
1982 .swapchain = swapchain_handle,
1983 .imageIndex = idx,
1984 };
1985 VkNativeBufferANDROID nb = {
1986 .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
1987 .pNext = &bimsi,
1988 .handle = buffer->handle,
1989 .stride = buffer->stride,
1990 .format = buffer->format,
1991 .usage = int(buffer->usage),
1992 };
1993 VkBindImageMemoryInfo bimi = {
1994 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
1995 .pNext = &nb,
1996 .image = swapchain.images[idx].image,
1997 .memory = VK_NULL_HANDLE,
1998 .memoryOffset = 0,
1999 };
2000 result = GetData(device).driver.BindImageMemory2(device, 1, &bimi);
2001 if (result != VK_SUCCESS) {
2002 // This shouldn't really happen. If it does, something is probably
2003 // unrecoverably wrong with the swapchain and its images. Cancel
2004 // the buffer and declare the swapchain broken.
2005 ALOGE("failed to do deferred gralloc buffer bind");
2006 window->cancelBuffer(window, buffer, fence_fd);
2007 return VK_ERROR_OUT_OF_DATE_KHR;
2008 }
2009
2010 swapchain.images[idx].dequeued = true;
2011 swapchain.images[idx].dequeue_fence = fence_fd;
2012 swapchain.images[idx].buffer = buffer;
2013 break;
2014 }
2015 }
2016 }
2017
2018 // The buffer doesn't match any slot. This shouldn't normally happen, but is
2019 // possible if the bufferqueue is reconfigured behind libvulkan's back. If this
2020 // happens, just declare the swapchain to be broken and the app will recreate it.
2021 if (idx == swapchain.num_images) {
2022 ALOGE("dequeueBuffer returned unrecognized buffer");
2023 window->cancelBuffer(window, buffer, fence_fd);
2024 return VK_ERROR_OUT_OF_DATE_KHR;
2025 }
2026
2027 int fence_clone = -1;
2028 if (fence_fd != -1) {
2029 fence_clone = dup(fence_fd);
2030 if (fence_clone == -1) {
2031 ALOGE("dup(fence) failed, stalling until signalled: %s (%d)",
2032 strerror(errno), errno);
2033 sync_wait(fence_fd, -1 /* forever */);
2034 }
2035 }
2036
2037 result = GetData(device).driver.AcquireImageANDROID(
2038 device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence);
2039 if (result != VK_SUCCESS) {
2040 // NOTE: we're relying on AcquireImageANDROID to close fence_clone,
2041 // even if the call fails. We could close it ourselves on failure, but
2042 // that would create a race condition if the driver closes it on a
2043 // failure path: some other thread might create an fd with the same
2044 // number between the time the driver closes it and the time we close
2045 // it. We must assume one of: the driver *always* closes it even on
2046 // failure, or *never* closes it on failure.
2047 window->cancelBuffer(window, buffer, fence_fd);
2048 swapchain.images[idx].dequeued = false;
2049 swapchain.images[idx].dequeue_fence = -1;
2050 return result;
2051 }
2052
2053 *image_index = idx;
2054 return VK_SUCCESS;
2055 }
2056
2057 VKAPI_ATTR
AcquireNextImage2KHR(VkDevice device,const VkAcquireNextImageInfoKHR * pAcquireInfo,uint32_t * pImageIndex)2058 VkResult AcquireNextImage2KHR(VkDevice device,
2059 const VkAcquireNextImageInfoKHR* pAcquireInfo,
2060 uint32_t* pImageIndex) {
2061 ATRACE_CALL();
2062
2063 return AcquireNextImageKHR(device, pAcquireInfo->swapchain,
2064 pAcquireInfo->timeout, pAcquireInfo->semaphore,
2065 pAcquireInfo->fence, pImageIndex);
2066 }
2067
WorstPresentResult(VkResult a,VkResult b)2068 static VkResult WorstPresentResult(VkResult a, VkResult b) {
2069 // See the error ranking for vkQueuePresentKHR at the end of section 29.6
2070 // (in spec version 1.0.14).
2071 static const VkResult kWorstToBest[] = {
2072 VK_ERROR_DEVICE_LOST,
2073 VK_ERROR_SURFACE_LOST_KHR,
2074 VK_ERROR_OUT_OF_DATE_KHR,
2075 VK_ERROR_OUT_OF_DEVICE_MEMORY,
2076 VK_ERROR_OUT_OF_HOST_MEMORY,
2077 VK_SUBOPTIMAL_KHR,
2078 };
2079 for (auto result : kWorstToBest) {
2080 if (a == result || b == result)
2081 return result;
2082 }
2083 ALOG_ASSERT(a == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", a);
2084 ALOG_ASSERT(b == VK_SUCCESS, "invalid vkQueuePresentKHR result %d", b);
2085 return a != VK_SUCCESS ? a : b;
2086 }
2087
2088 // KHR_incremental_present aspect of QueuePresentKHR
SetSwapchainSurfaceDamage(ANativeWindow * window,const VkPresentRegionKHR * pRegion)2089 static void SetSwapchainSurfaceDamage(ANativeWindow *window, const VkPresentRegionKHR *pRegion) {
2090 std::vector<android_native_rect_t> rects(pRegion->rectangleCount);
2091 for (auto i = 0u; i < pRegion->rectangleCount; i++) {
2092 auto const& rect = pRegion->pRectangles[i];
2093 if (rect.layer > 0) {
2094 ALOGV("vkQueuePresentKHR ignoring invalid layer (%u); using layer 0 instead",
2095 rect.layer);
2096 }
2097
2098 rects[i].left = rect.offset.x;
2099 rects[i].bottom = rect.offset.y;
2100 rects[i].right = rect.offset.x + rect.extent.width;
2101 rects[i].top = rect.offset.y + rect.extent.height;
2102 }
2103 native_window_set_surface_damage(window, rects.data(), rects.size());
2104 }
2105
2106 // GOOGLE_display_timing aspect of QueuePresentKHR
SetSwapchainFrameTimestamp(Swapchain & swapchain,const VkPresentTimeGOOGLE * pTime)2107 static void SetSwapchainFrameTimestamp(Swapchain &swapchain, const VkPresentTimeGOOGLE *pTime) {
2108 ANativeWindow *window = swapchain.surface.window.get();
2109
2110 // We don't know whether the app will actually use GOOGLE_display_timing
2111 // with a particular swapchain until QueuePresent; enable it on the BQ
2112 // now if needed
2113 if (!swapchain.frame_timestamps_enabled) {
2114 ALOGV("Calling native_window_enable_frame_timestamps(true)");
2115 native_window_enable_frame_timestamps(window, true);
2116 swapchain.frame_timestamps_enabled = true;
2117 }
2118
2119 // Record the nativeFrameId so it can be later correlated to
2120 // this present.
2121 uint64_t nativeFrameId = 0;
2122 int err = native_window_get_next_frame_id(
2123 window, &nativeFrameId);
2124 if (err != android::OK) {
2125 ALOGE("Failed to get next native frame ID.");
2126 }
2127
2128 // Add a new timing record with the user's presentID and
2129 // the nativeFrameId.
2130 swapchain.timing.emplace_back(pTime, nativeFrameId);
2131 if (swapchain.timing.size() > MAX_TIMING_INFOS) {
2132 swapchain.timing.erase(
2133 swapchain.timing.begin(),
2134 swapchain.timing.begin() + swapchain.timing.size() - MAX_TIMING_INFOS);
2135 }
2136 if (pTime->desiredPresentTime) {
2137 ALOGV(
2138 "Calling native_window_set_buffers_timestamp(%" PRId64 ")",
2139 pTime->desiredPresentTime);
2140 native_window_set_buffers_timestamp(
2141 window,
2142 static_cast<int64_t>(pTime->desiredPresentTime));
2143 }
2144 }
2145
2146 // EXT_swapchain_maintenance1 present mode change
SetSwapchainPresentMode(ANativeWindow * window,VkPresentModeKHR mode)2147 static bool SetSwapchainPresentMode(ANativeWindow *window, VkPresentModeKHR mode) {
2148 // There is no dynamic switching between non-shared present modes.
2149 // All we support is switching between demand and continuous refresh.
2150 if (!IsSharedPresentMode(mode))
2151 return true;
2152
2153 int err = native_window_set_auto_refresh(window,
2154 mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
2155 if (err != android::OK) {
2156 ALOGE("native_window_set_auto_refresh() failed: %s (%d)",
2157 strerror(-err), err);
2158 return false;
2159 }
2160
2161 return true;
2162 }
2163
PresentOneSwapchain(VkQueue queue,Swapchain & swapchain,uint32_t imageIndex,const VkPresentRegionKHR * pRegion,const VkPresentTimeGOOGLE * pTime,VkFence presentFence,const VkPresentModeKHR * pPresentMode,uint32_t waitSemaphoreCount,const VkSemaphore * pWaitSemaphores)2164 static VkResult PresentOneSwapchain(
2165 VkQueue queue,
2166 Swapchain& swapchain,
2167 uint32_t imageIndex,
2168 const VkPresentRegionKHR *pRegion,
2169 const VkPresentTimeGOOGLE *pTime,
2170 VkFence presentFence,
2171 const VkPresentModeKHR *pPresentMode,
2172 uint32_t waitSemaphoreCount,
2173 const VkSemaphore *pWaitSemaphores) {
2174
2175 VkDevice device = GetData(queue).driver_device;
2176 const auto& dispatch = GetData(queue).driver;
2177
2178 Swapchain::Image& img = swapchain.images[imageIndex];
2179 VkResult swapchain_result = VK_SUCCESS;
2180 VkResult result;
2181 int err;
2182
2183 // XXX: long standing issue: QueueSignalReleaseImageANDROID consumes the
2184 // wait semaphores, so this doesn't actually work for the multiple swapchain
2185 // case.
2186 int fence = -1;
2187 result = dispatch.QueueSignalReleaseImageANDROID(
2188 queue, waitSemaphoreCount,
2189 pWaitSemaphores, img.image, &fence);
2190 if (result != VK_SUCCESS) {
2191 ALOGE("QueueSignalReleaseImageANDROID failed: %d", result);
2192 swapchain_result = result;
2193 }
2194 if (img.release_fence >= 0)
2195 close(img.release_fence);
2196 img.release_fence = fence < 0 ? -1 : dup(fence);
2197
2198 if (swapchain.surface.swapchain_handle == HandleFromSwapchain(&swapchain)) {
2199 ANativeWindow* window = swapchain.surface.window.get();
2200 if (swapchain_result == VK_SUCCESS) {
2201
2202 if (presentFence != VK_NULL_HANDLE) {
2203 int fence_copy = fence < 0 ? -1 : dup(fence);
2204 VkImportFenceFdInfoKHR iffi = {
2205 VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
2206 nullptr,
2207 presentFence,
2208 VK_FENCE_IMPORT_TEMPORARY_BIT,
2209 VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
2210 fence_copy,
2211 };
2212 if (VK_SUCCESS != dispatch.ImportFenceFdKHR(device, &iffi) && fence_copy >= 0) {
2213 // ImportFenceFdKHR takes ownership only if it succeeds
2214 close(fence_copy);
2215 }
2216 }
2217
2218 if (pRegion) {
2219 SetSwapchainSurfaceDamage(window, pRegion);
2220 }
2221 if (pTime) {
2222 SetSwapchainFrameTimestamp(swapchain, pTime);
2223 }
2224 if (pPresentMode) {
2225 if (!SetSwapchainPresentMode(window, *pPresentMode))
2226 swapchain_result = WorstPresentResult(swapchain_result,
2227 VK_ERROR_SURFACE_LOST_KHR);
2228 }
2229
2230 err = window->queueBuffer(window, img.buffer.get(), fence);
2231 // queueBuffer always closes fence, even on error
2232 if (err != android::OK) {
2233 ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
2234 swapchain_result = WorstPresentResult(
2235 swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
2236 } else {
2237 if (img.dequeue_fence >= 0) {
2238 close(img.dequeue_fence);
2239 img.dequeue_fence = -1;
2240 }
2241 img.dequeued = false;
2242 }
2243
2244 // If the swapchain is in shared mode, immediately dequeue the
2245 // buffer so it can be presented again without an intervening
2246 // call to AcquireNextImageKHR. We expect to get the same buffer
2247 // back from every call to dequeueBuffer in this mode.
2248 if (swapchain.shared && swapchain_result == VK_SUCCESS) {
2249 ANativeWindowBuffer* buffer;
2250 int fence_fd;
2251 err = window->dequeueBuffer(window, &buffer, &fence_fd);
2252 if (err != android::OK) {
2253 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
2254 swapchain_result = WorstPresentResult(swapchain_result,
2255 VK_ERROR_SURFACE_LOST_KHR);
2256 } else if (img.buffer != buffer) {
2257 ALOGE("got wrong image back for shared swapchain");
2258 swapchain_result = WorstPresentResult(swapchain_result,
2259 VK_ERROR_SURFACE_LOST_KHR);
2260 } else {
2261 img.dequeue_fence = fence_fd;
2262 img.dequeued = true;
2263 }
2264 }
2265 }
2266 if (swapchain_result != VK_SUCCESS) {
2267 OrphanSwapchain(device, &swapchain);
2268 }
2269 // Android will only return VK_SUBOPTIMAL_KHR for vkQueuePresentKHR,
2270 // and only when the window's transform/rotation changes. Extent
2271 // changes will not cause VK_SUBOPTIMAL_KHR because of the
2272 // application issues that were caused when the following transform
2273 // change was added.
2274 int window_transform_hint;
2275 err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
2276 &window_transform_hint);
2277 if (err != android::OK) {
2278 ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
2279 strerror(-err), err);
2280 swapchain_result = WorstPresentResult(
2281 swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
2282 }
2283 if (swapchain.pre_transform != window_transform_hint) {
2284 swapchain_result =
2285 WorstPresentResult(swapchain_result, VK_SUBOPTIMAL_KHR);
2286 }
2287 } else {
2288 ReleaseSwapchainImage(device, swapchain.shared, nullptr, fence,
2289 img, true);
2290 swapchain_result = VK_ERROR_OUT_OF_DATE_KHR;
2291 }
2292
2293 return swapchain_result;
2294 }
2295
2296 VKAPI_ATTR
QueuePresentKHR(VkQueue queue,const VkPresentInfoKHR * present_info)2297 VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
2298 ATRACE_CALL();
2299
2300 ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
2301 "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
2302 present_info->sType);
2303
2304 VkResult final_result = VK_SUCCESS;
2305
2306 // Look at the pNext chain for supported extension structs:
2307 const VkPresentRegionsKHR* present_regions = nullptr;
2308 const VkPresentTimesInfoGOOGLE* present_times = nullptr;
2309 const VkSwapchainPresentFenceInfoEXT* present_fences = nullptr;
2310 const VkSwapchainPresentModeInfoEXT* present_modes = nullptr;
2311
2312 const VkPresentRegionsKHR* next =
2313 reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext);
2314 while (next) {
2315 switch (next->sType) {
2316 case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
2317 present_regions = next;
2318 break;
2319 case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE:
2320 present_times =
2321 reinterpret_cast<const VkPresentTimesInfoGOOGLE*>(next);
2322 break;
2323 case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT:
2324 present_fences =
2325 reinterpret_cast<const VkSwapchainPresentFenceInfoEXT*>(next);
2326 break;
2327 case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT:
2328 present_modes =
2329 reinterpret_cast<const VkSwapchainPresentModeInfoEXT*>(next);
2330 break;
2331 default:
2332 ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x",
2333 next->sType);
2334 break;
2335 }
2336 next = reinterpret_cast<const VkPresentRegionsKHR*>(next->pNext);
2337 }
2338 ALOGV_IF(
2339 present_regions &&
2340 present_regions->swapchainCount != present_info->swapchainCount,
2341 "VkPresentRegions::swapchainCount != VkPresentInfo::swapchainCount");
2342 ALOGV_IF(present_times &&
2343 present_times->swapchainCount != present_info->swapchainCount,
2344 "VkPresentTimesInfoGOOGLE::swapchainCount != "
2345 "VkPresentInfo::swapchainCount");
2346 ALOGV_IF(present_fences &&
2347 present_fences->swapchainCount != present_info->swapchainCount,
2348 "VkSwapchainPresentFenceInfoEXT::swapchainCount != "
2349 "VkPresentInfo::swapchainCount");
2350 ALOGV_IF(present_modes &&
2351 present_modes->swapchainCount != present_info->swapchainCount,
2352 "VkSwapchainPresentModeInfoEXT::swapchainCount != "
2353 "VkPresentInfo::swapchainCount");
2354
2355 const VkPresentRegionKHR* regions =
2356 (present_regions) ? present_regions->pRegions : nullptr;
2357 const VkPresentTimeGOOGLE* times =
2358 (present_times) ? present_times->pTimes : nullptr;
2359
2360 for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
2361 Swapchain& swapchain =
2362 *SwapchainFromHandle(present_info->pSwapchains[sc]);
2363
2364 VkResult swapchain_result = PresentOneSwapchain(
2365 queue,
2366 swapchain,
2367 present_info->pImageIndices[sc],
2368 (regions && !swapchain.mailbox_mode) ? ®ions[sc] : nullptr,
2369 times ? ×[sc] : nullptr,
2370 present_fences ? present_fences->pFences[sc] : VK_NULL_HANDLE,
2371 present_modes ? &present_modes->pPresentModes[sc] : nullptr,
2372 present_info->waitSemaphoreCount,
2373 present_info->pWaitSemaphores);
2374
2375 if (present_info->pResults)
2376 present_info->pResults[sc] = swapchain_result;
2377
2378 if (swapchain_result != final_result)
2379 final_result = WorstPresentResult(final_result, swapchain_result);
2380 }
2381
2382 return final_result;
2383 }
2384
2385 VKAPI_ATTR
GetRefreshCycleDurationGOOGLE(VkDevice,VkSwapchainKHR swapchain_handle,VkRefreshCycleDurationGOOGLE * pDisplayTimingProperties)2386 VkResult GetRefreshCycleDurationGOOGLE(
2387 VkDevice,
2388 VkSwapchainKHR swapchain_handle,
2389 VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
2390 ATRACE_CALL();
2391
2392 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
2393 VkResult result = swapchain.get_refresh_duration(pDisplayTimingProperties->refreshDuration);
2394
2395 return result;
2396 }
2397
2398 VKAPI_ATTR
GetPastPresentationTimingGOOGLE(VkDevice,VkSwapchainKHR swapchain_handle,uint32_t * count,VkPastPresentationTimingGOOGLE * timings)2399 VkResult GetPastPresentationTimingGOOGLE(
2400 VkDevice,
2401 VkSwapchainKHR swapchain_handle,
2402 uint32_t* count,
2403 VkPastPresentationTimingGOOGLE* timings) {
2404 ATRACE_CALL();
2405
2406 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
2407 if (swapchain.surface.swapchain_handle != swapchain_handle) {
2408 return VK_ERROR_OUT_OF_DATE_KHR;
2409 }
2410
2411 ANativeWindow* window = swapchain.surface.window.get();
2412 VkResult result = VK_SUCCESS;
2413
2414 if (!swapchain.frame_timestamps_enabled) {
2415 ALOGV("Calling native_window_enable_frame_timestamps(true)");
2416 native_window_enable_frame_timestamps(window, true);
2417 swapchain.frame_timestamps_enabled = true;
2418 }
2419
2420 if (timings) {
2421 // Get the latest ready timing count before copying, since the copied
2422 // timing info will be erased in copy_ready_timings function.
2423 uint32_t n = get_num_ready_timings(swapchain);
2424 copy_ready_timings(swapchain, count, timings);
2425 // Check the *count here against the recorded ready timing count, since
2426 // *count can be overwritten per spec describes.
2427 if (*count < n) {
2428 result = VK_INCOMPLETE;
2429 }
2430 } else {
2431 *count = get_num_ready_timings(swapchain);
2432 }
2433
2434 return result;
2435 }
2436
2437 VKAPI_ATTR
GetSwapchainStatusKHR(VkDevice,VkSwapchainKHR swapchain_handle)2438 VkResult GetSwapchainStatusKHR(
2439 VkDevice,
2440 VkSwapchainKHR swapchain_handle) {
2441 ATRACE_CALL();
2442
2443 Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
2444 VkResult result = VK_SUCCESS;
2445
2446 if (swapchain.surface.swapchain_handle != swapchain_handle) {
2447 return VK_ERROR_OUT_OF_DATE_KHR;
2448 }
2449
2450 // TODO(b/143296009): Implement this function properly
2451
2452 return result;
2453 }
2454
SetHdrMetadataEXT(VkDevice,uint32_t swapchainCount,const VkSwapchainKHR * pSwapchains,const VkHdrMetadataEXT * pHdrMetadataEXTs)2455 VKAPI_ATTR void SetHdrMetadataEXT(
2456 VkDevice,
2457 uint32_t swapchainCount,
2458 const VkSwapchainKHR* pSwapchains,
2459 const VkHdrMetadataEXT* pHdrMetadataEXTs) {
2460 ATRACE_CALL();
2461
2462 for (uint32_t idx = 0; idx < swapchainCount; idx++) {
2463 Swapchain* swapchain = SwapchainFromHandle(pSwapchains[idx]);
2464 if (!swapchain)
2465 continue;
2466
2467 if (swapchain->surface.swapchain_handle != pSwapchains[idx]) continue;
2468
2469 ANativeWindow* window = swapchain->surface.window.get();
2470
2471 VkHdrMetadataEXT vulkanMetadata = pHdrMetadataEXTs[idx];
2472 const android_smpte2086_metadata smpteMetdata = {
2473 {vulkanMetadata.displayPrimaryRed.x,
2474 vulkanMetadata.displayPrimaryRed.y},
2475 {vulkanMetadata.displayPrimaryGreen.x,
2476 vulkanMetadata.displayPrimaryGreen.y},
2477 {vulkanMetadata.displayPrimaryBlue.x,
2478 vulkanMetadata.displayPrimaryBlue.y},
2479 {vulkanMetadata.whitePoint.x, vulkanMetadata.whitePoint.y},
2480 vulkanMetadata.maxLuminance,
2481 vulkanMetadata.minLuminance};
2482 native_window_set_buffers_smpte2086_metadata(window, &smpteMetdata);
2483
2484 const android_cta861_3_metadata cta8613Metadata = {
2485 vulkanMetadata.maxContentLightLevel,
2486 vulkanMetadata.maxFrameAverageLightLevel};
2487 native_window_set_buffers_cta861_3_metadata(window, &cta8613Metadata);
2488 }
2489
2490 return;
2491 }
2492
InterceptBindImageMemory2(uint32_t bind_info_count,const VkBindImageMemoryInfo * bind_infos,std::vector<VkNativeBufferANDROID> * out_native_buffers,std::vector<VkBindImageMemoryInfo> * out_bind_infos)2493 static void InterceptBindImageMemory2(
2494 uint32_t bind_info_count,
2495 const VkBindImageMemoryInfo* bind_infos,
2496 std::vector<VkNativeBufferANDROID>* out_native_buffers,
2497 std::vector<VkBindImageMemoryInfo>* out_bind_infos) {
2498 out_native_buffers->clear();
2499 out_bind_infos->clear();
2500
2501 if (!bind_info_count)
2502 return;
2503
2504 std::unordered_set<uint32_t> intercepted_indexes;
2505
2506 for (uint32_t idx = 0; idx < bind_info_count; idx++) {
2507 auto info = reinterpret_cast<const VkBindImageMemorySwapchainInfoKHR*>(
2508 bind_infos[idx].pNext);
2509 while (info &&
2510 info->sType !=
2511 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR) {
2512 info = reinterpret_cast<const VkBindImageMemorySwapchainInfoKHR*>(
2513 info->pNext);
2514 }
2515
2516 if (!info)
2517 continue;
2518
2519 ALOG_ASSERT(info->swapchain != VK_NULL_HANDLE,
2520 "swapchain handle must not be NULL");
2521 const Swapchain* swapchain = SwapchainFromHandle(info->swapchain);
2522 ALOG_ASSERT(
2523 info->imageIndex < swapchain->num_images,
2524 "imageIndex must be less than the number of images in swapchain");
2525
2526 ANativeWindowBuffer* buffer =
2527 swapchain->images[info->imageIndex].buffer.get();
2528 VkNativeBufferANDROID native_buffer = {
2529 #pragma clang diagnostic push
2530 #pragma clang diagnostic ignored "-Wold-style-cast"
2531 .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
2532 #pragma clang diagnostic pop
2533 .pNext = bind_infos[idx].pNext,
2534 .handle = buffer->handle,
2535 .stride = buffer->stride,
2536 .format = buffer->format,
2537 .usage = int(buffer->usage),
2538 };
2539 // Reserve enough space to avoid letting re-allocation invalidate the
2540 // addresses of the elements inside.
2541 out_native_buffers->reserve(bind_info_count);
2542 out_native_buffers->emplace_back(native_buffer);
2543
2544 // Reserve the space now since we know how much is needed now.
2545 out_bind_infos->reserve(bind_info_count);
2546 out_bind_infos->emplace_back(bind_infos[idx]);
2547 out_bind_infos->back().pNext = &out_native_buffers->back();
2548
2549 intercepted_indexes.insert(idx);
2550 }
2551
2552 if (intercepted_indexes.empty())
2553 return;
2554
2555 for (uint32_t idx = 0; idx < bind_info_count; idx++) {
2556 if (intercepted_indexes.count(idx))
2557 continue;
2558 out_bind_infos->emplace_back(bind_infos[idx]);
2559 }
2560 }
2561
2562 VKAPI_ATTR
BindImageMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)2563 VkResult BindImageMemory2(VkDevice device,
2564 uint32_t bindInfoCount,
2565 const VkBindImageMemoryInfo* pBindInfos) {
2566 ATRACE_CALL();
2567
2568 // out_native_buffers is for maintaining the lifecycle of the constructed
2569 // VkNativeBufferANDROID objects inside InterceptBindImageMemory2.
2570 std::vector<VkNativeBufferANDROID> out_native_buffers;
2571 std::vector<VkBindImageMemoryInfo> out_bind_infos;
2572 InterceptBindImageMemory2(bindInfoCount, pBindInfos, &out_native_buffers,
2573 &out_bind_infos);
2574 return GetData(device).driver.BindImageMemory2(
2575 device, bindInfoCount,
2576 out_bind_infos.empty() ? pBindInfos : out_bind_infos.data());
2577 }
2578
2579 VKAPI_ATTR
BindImageMemory2KHR(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)2580 VkResult BindImageMemory2KHR(VkDevice device,
2581 uint32_t bindInfoCount,
2582 const VkBindImageMemoryInfo* pBindInfos) {
2583 ATRACE_CALL();
2584
2585 std::vector<VkNativeBufferANDROID> out_native_buffers;
2586 std::vector<VkBindImageMemoryInfo> out_bind_infos;
2587 InterceptBindImageMemory2(bindInfoCount, pBindInfos, &out_native_buffers,
2588 &out_bind_infos);
2589 return GetData(device).driver.BindImageMemory2KHR(
2590 device, bindInfoCount,
2591 out_bind_infos.empty() ? pBindInfos : out_bind_infos.data());
2592 }
2593
2594 VKAPI_ATTR
ReleaseSwapchainImagesEXT(VkDevice,const VkReleaseSwapchainImagesInfoEXT * pReleaseInfo)2595 VkResult ReleaseSwapchainImagesEXT(VkDevice /*device*/,
2596 const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo) {
2597 ATRACE_CALL();
2598
2599 Swapchain& swapchain = *SwapchainFromHandle(pReleaseInfo->swapchain);
2600 ANativeWindow* window = swapchain.surface.window.get();
2601
2602 // If in shared present mode, don't actually release the image back to the BQ.
2603 // Both sides share it forever.
2604 if (swapchain.shared)
2605 return VK_SUCCESS;
2606
2607 for (uint32_t i = 0; i < pReleaseInfo->imageIndexCount; i++) {
2608 Swapchain::Image& img = swapchain.images[pReleaseInfo->pImageIndices[i]];
2609 window->cancelBuffer(window, img.buffer.get(), img.dequeue_fence);
2610
2611 // cancelBuffer has taken ownership of the dequeue fence
2612 img.dequeue_fence = -1;
2613 // if we're still holding a release fence, get rid of it now
2614 if (img.release_fence >= 0) {
2615 close(img.release_fence);
2616 img.release_fence = -1;
2617 }
2618 img.dequeued = false;
2619 }
2620
2621 return VK_SUCCESS;
2622 }
2623
2624 } // namespace driver
2625 } // namespace vulkan
2626