blob: 5e9fa0970608ee2030c9ebe7d82b3874588eacda [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_LIB_VULKAN_SWAPCHAIN_IMAGE_PIPE_SURFACE_ASYNC_H_
#define SRC_LIB_VULKAN_SWAPCHAIN_IMAGE_PIPE_SURFACE_ASYNC_H_
#include <fuchsia/sysmem2/cpp/fidl.h>
#include <fuchsia/ui/composition/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/task.h>
#include <mutex>
#include "image_pipe_surface.h"
#include "src/lib/ui/flatland-frame-scheduling/src/simple_present.h"
namespace image_pipe_swapchain {
// An implementation of ImagePipeSurface based on an async fidl Flatland.
class ImagePipeSurfaceAsync : public ImagePipeSurface {
public:
explicit ImagePipeSurfaceAsync(zx_handle_t view_creation_token_handle)
: loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {
loop_.StartThread();
view_creation_token_.value = zx::channel(view_creation_token_handle);
std::vector<VkSurfaceFormatKHR> formats(
{{VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR},
{VK_FORMAT_R8G8B8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR},
{VK_FORMAT_B8G8R8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR},
{VK_FORMAT_B8G8R8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR}});
supported_image_properties_ = {formats};
}
~ImagePipeSurfaceAsync() override {
async::PostTask(loop_.dispatcher(), [this] {
// flatland_ and flatland_allocator_ are thread hostile so it must be turn down on the thread
// that will use it.
flatland_connection_.reset();
flatland_allocator_ = nullptr;
loop_.Quit();
});
loop_.JoinThreads();
}
bool Init() override;
bool IsLost() override;
bool CreateImage(VkDevice device, VkLayerDispatchTable* pDisp, VkFormat format,
VkImageUsageFlags usage, VkSwapchainCreateFlagsKHR swapchain_flags,
VkExtent2D extent, uint32_t image_count, const VkAllocationCallbacks* pAllocator,
std::vector<ImageInfo>* image_info_out) override;
void RemoveImage(uint32_t image_id) override;
void PresentImage(uint32_t image_id, std::vector<std::unique_ptr<PlatformEvent>> acquire_fences,
std::vector<std::unique_ptr<PlatformEvent>> release_fences,
VkQueue queue) override;
SupportedImageProperties& GetSupportedImageProperties() override;
private:
class FenceSignaler {
public:
explicit FenceSignaler(zx::event event) : event_(std::move(event)) {}
~FenceSignaler() {
if (event_)
event_.signal(0, ZX_EVENT_SIGNALED);
}
const zx::event& event() { return event_; }
void reset() { event_.reset(); }
private:
zx::event event_;
};
// Called on the async loop.
void PresentNextImageLocked() __attribute__((requires_capability(mutex_)));
void OnErrorLocked() __attribute__((requires_capability(mutex_)));
async::Loop loop_;
std::mutex mutex_;
// Can only be accessed from the async loop's thread.
std::unique_ptr<simple_present::FlatlandConnection> flatland_connection_;
fuchsia::ui::composition::AllocatorPtr flatland_allocator_;
fuchsia::ui::views::ViewCreationToken view_creation_token_;
fuchsia::sysmem2::AllocatorSyncPtr sysmem_allocator_;
struct PendingPresent {
uint32_t image_id;
std::vector<zx::event> acquire_fences;
// These fences will automatically be signaled when they go out of scope, which could happen if
// the Flatland channel is closed. As these events are passed to the application as acquire
// semaphores, this prevents semaphore waits on them from hanging until the GPU driver decides
// to time them out.
// The only case where we don't automatically signal them is if the OnFramePresented callback is
// run, in which case scenic is responsible for signaling them.
std::vector<std::unique_ptr<FenceSignaler>> release_fences;
};
std::vector<PendingPresent> queue_ __attribute__((guarded_by(mutex_)));
bool present_pending_ __attribute__((guarded_by(mutex_))) = false;
std::vector<std::unique_ptr<FenceSignaler>> previous_present_release_fences_
__attribute__((guarded_by(mutex_)));
SupportedImageProperties supported_image_properties_;
bool channel_closed_ __attribute__((guarded_by(mutex_))) = false;
};
} // namespace image_pipe_swapchain
#endif // SRC_LIB_VULKAN_SWAPCHAIN_IMAGE_PIPE_SURFACE_ASYNC_H_