--- /dev/null
+#include <array>
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+
+#include <unistd.h>
+#include <vulkan/vulkan.h>
+
+#include "swapchain_base_tizen.hpp"
+
+#if VULKAN_WSI_DEBUG > 0
+#define WSI_PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__)
+#else
+#define WSI_PRINT_ERROR(...) (void)0
+#endif
+
+namespace wsi
+{
+
+swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *callbacks)
+ : m_device_data(dev_data)
+ , m_allocator(callbacks, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)
+ , m_swapchain_images(m_allocator)
+ , m_surface(VK_NULL_HANDLE)
+ , m_present_mode(VK_PRESENT_MODE_IMMEDIATE_KHR)
+ , m_descendant(VK_NULL_HANDLE)
+ , m_ancestor(VK_NULL_HANDLE)
+ , m_device(VK_NULL_HANDLE)
+ , m_queue(VK_NULL_HANDLE)
+{
+}
+
+VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
+{
+ assert(device != VK_NULL_HANDLE);
+ assert(swapchain_create_info != nullptr);
+ assert(swapchain_create_info->surface != VK_NULL_HANDLE);
+
+ VkResult result;
+
+ m_device = device;
+ m_surface = swapchain_create_info->surface;
+
+ /* We have allocated images, we can call the platform init function if something needs to be done. */
+ result = init_platform(device, swapchain_create_info);
+ if (result != VK_SUCCESS)
+ {
+ return result;
+ }
+
+ VkImageCreateInfo image_create_info = {};
+ image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ image_create_info.pNext = nullptr;
+ image_create_info.imageType = VK_IMAGE_TYPE_2D;
+ image_create_info.format = swapchain_create_info->imageFormat;
+ image_create_info.extent = { swapchain_create_info->imageExtent.width, swapchain_create_info->imageExtent.height, 1 };
+ image_create_info.mipLevels = 1;
+ image_create_info.arrayLayers = swapchain_create_info->imageArrayLayers;
+ image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
+ image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
+ image_create_info.usage = swapchain_create_info->imageUsage;
+ image_create_info.flags = 0;
+ image_create_info.sharingMode = swapchain_create_info->imageSharingMode;
+ image_create_info.queueFamilyIndexCount = swapchain_create_info->queueFamilyIndexCount;
+ image_create_info.pQueueFamilyIndices = swapchain_create_info->pQueueFamilyIndices;
+ image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ result = create_image(image_create_info);
+ if (result != VK_SUCCESS)
+ {
+ return result;
+ }
+
+ m_device_data.disp.GetDeviceQueue(m_device, 0, 0, &m_queue);
+ result = m_device_data.SetDeviceLoaderData(m_device, m_queue);
+ if (VK_SUCCESS != result)
+ {
+ return result;
+ }
+
+ if (swapchain_create_info->oldSwapchain != VK_NULL_HANDLE)
+ {
+ /* TO BE DONE - How to reuse the old swapchain */
+ /*
+ m_ancestor = swapchain_create_info->oldSwapchain;
+
+ auto *ancestor = reinterpret_cast<swapchain_base *>(m_ancestor);
+ ancestor->deprecate(reinterpret_cast<VkSwapchainKHR>(this));
+ */
+ }
+
+ return VK_SUCCESS;
+}
+
+void swapchain_base::teardown()
+{
+ if (m_queue != VK_NULL_HANDLE)
+ {
+ /* Make sure the vkFences are done signaling. */
+ m_device_data.disp.QueueWaitIdle(m_queue);
+ }
+}
+
+VkResult swapchain_base::acquire_next_image(uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *image_index)
+{
+ VkResult retval;
+
+ retval = acquire_image(image_index);
+ if (retval != VK_SUCCESS)
+ return retval;
+
+ if (VK_NULL_HANDLE != semaphore || VK_NULL_HANDLE != fence)
+ {
+ VkSubmitInfo submit = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
+
+ if (VK_NULL_HANDLE != semaphore)
+ {
+ submit.signalSemaphoreCount = 1;
+ submit.pSignalSemaphores = &semaphore;
+ }
+
+ submit.commandBufferCount = 0;
+ submit.pCommandBuffers = nullptr;
+ retval = m_device_data.disp.QueueSubmit(m_queue, 1, &submit, fence);
+ assert(retval == VK_SUCCESS);
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult swapchain_base::get_swapchain_images(uint32_t *swapchain_image_count, VkImage *swapchain_images)
+{
+ if (swapchain_images == nullptr)
+ {
+ /* Return the number of swapchain images. */
+ *swapchain_image_count = m_swapchain_images.size();
+
+ return VK_SUCCESS;
+ }
+ else
+ {
+ assert(m_swapchain_images.size() > 0);
+ assert(*swapchain_image_count > 0);
+
+ /* Populate array, write actual number of images returned. */
+ uint32_t current_image = 0;
+
+ do
+ {
+ swapchain_images[current_image] = m_swapchain_images[current_image].image;
+
+ current_image++;
+
+ if (current_image == m_swapchain_images.size())
+ {
+ *swapchain_image_count = current_image;
+
+ return VK_SUCCESS;
+ }
+
+ } while (current_image < *swapchain_image_count);
+
+ /* If swapchain_image_count is smaller than the number of presentable images
+ * in the swapchain, VK_INCOMPLETE must be returned instead of VK_SUCCESS. */
+ *swapchain_image_count = current_image;
+
+ return VK_INCOMPLETE;
+ }
+}
+
+VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *present_info, const uint32_t image_index)
+{
+ VkResult result;
+
+ /* When the semaphore that comes in is signalled, we know that all work is done. So, we do not
+ * want to block any future Vulkan queue work on it. So, we pass in BOTTOM_OF_PIPE bit as the
+ * wait flag.
+ */
+ VkPipelineStageFlags pipeline_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+
+ VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ NULL,
+ present_info->waitSemaphoreCount,
+ present_info->pWaitSemaphores,
+ &pipeline_stage_flags,
+ 0,
+ NULL,
+ 0,
+ NULL };
+
+ result = m_device_data.disp.ResetFences(m_device, 1, &m_swapchain_images[image_index].present_fence);
+ if (result != VK_SUCCESS)
+ {
+ return result;
+ }
+
+ result = m_device_data.disp.QueueSubmit(queue, 1, &submit_info, m_swapchain_images[image_index].present_fence);
+ if (result != VK_SUCCESS)
+ {
+ return result;
+ }
+
+ present_image(image_index);
+
+ return VK_SUCCESS;
+}
+
+void swapchain_base::deprecate(VkSwapchainKHR descendant)
+{
+ // TO BE DONE - release old swapchain resources
+}
+
+void swapchain_base::clear_ancestor()
+{
+ m_ancestor = VK_NULL_HANDLE;
+}
+
+void swapchain_base::clear_descendant()
+{
+ m_descendant = VK_NULL_HANDLE;
+}
+
+#undef WSI_PRINT_ERROR
+
+} /* namespace wsi */
+
--- /dev/null
+#pragma once
+
+#include <vulkan/vulkan.h>
+
+#include <layer/private_data.hpp>
+#include <util/timed_semaphore.hpp>
+#include <util/custom_allocator.hpp>
+
+namespace wsi
+{
+struct swapchain_image
+{
+ /* Implementation specific data */
+ void *data{nullptr};
+
+ VkImage image{VK_NULL_HANDLE};
+ VkFence present_fence{VK_NULL_HANDLE};
+};
+
+/**
+ * @brief Base swapchain class
+ *
+ * - the swapchain implementations inherit from this class.
+ * - the VkSwapchain will hold a pointer to this class.
+ * - much of the swapchain implementation is done by this class, as the only things needed
+ * in the implementation are how to create a presentable image and how to present an image.
+ */
+class swapchain_base
+{
+public:
+ swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *allocator);
+
+ virtual ~swapchain_base()
+ {
+ /* nop */
+ }
+
+ /**
+ * @brief Create swapchain.
+ *
+ * Perform all swapchain initialization, create presentable images etc.
+ */
+ VkResult init(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info);
+
+ /**
+ * @brief Acquires a free image.
+ *
+ * Current implementation blocks until a free image is available.
+ *
+ * @param timeout Unused since we block until a free image is available.
+ *
+ * @param semaphore A semaphore signaled once an image is acquired.
+ *
+ * @param fence A fence signaled once an image is acquired.
+ *
+ * @param pImageIndex The index of the acquired image.
+ *
+ * @return VK_SUCCESS on completion.
+ */
+ VkResult acquire_next_image(uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *image_index);
+
+ /**
+ * @brief Gets the number of swapchain images or a number of at most
+ * m_num_swapchain_images images.
+ *
+ * @param pSwapchainImageCount Used to return number of images in
+ * the swapchain if second parameter is nullptr or represents the
+ * number of images to be returned in second parameter.
+ *
+ * @param pSwapchainImage Array of VkImage handles.
+ *
+ * @return If number of requested images is less than the number of available
+ * images in the swapchain returns VK_INCOMPLETE otherwise VK_SUCCESS.
+ */
+ VkResult get_swapchain_images(uint32_t *swapchain_image_count, VkImage *swapchain_image);
+
+ /**
+ * @brief Submits a present request for the supplied image.
+ *
+ * @param queue The queue to which the submission will be made to.
+ *
+ * @param pPresentInfo Information about the swapchain and image to be presented.
+ *
+ * @param imageIndex The index of the image to be presented.
+ *
+ * @return If queue submission fails returns error of vkQueueSubmit, if the
+ * swapchain has a descendant who started presenting returns VK_ERROR_OUT_OF_DATE_KHR,
+ * otherwise returns VK_SUCCESS.
+ */
+ VkResult queue_present(VkQueue queue, const VkPresentInfoKHR *present_info, const uint32_t image_index);
+
+protected:
+
+ layer::device_private_data &m_device_data;
+
+ /**
+ * @brief User provided memory allocation callbacks.
+ */
+ const util::allocator m_allocator;
+
+ /**
+ * @brief Vector of images in the swapchain.
+ */
+ util::vector<swapchain_image> m_swapchain_images;
+
+ /**
+ * @brief Handle to the surface object this swapchain will present images to.
+ */
+ VkSurfaceKHR m_surface;
+
+ /**
+ * @brief present mode to use for this swapchain
+ */
+ VkPresentModeKHR m_present_mode;
+
+ /**
+ * @brief Descendant of this swapchain.
+ * Used to check whether or not a descendant of this swapchain has started
+ * presenting images to the surface already. If it has, any calls to queuePresent
+ * for this swapchain will return VK_ERROR_OUT_OF_DATE_KHR.
+ */
+ VkSwapchainKHR m_descendant;
+
+ /**
+ * @brief Ancestor of this swapchain.
+ * Used to check whether the ancestor swapchain has completed all of its
+ * pending page flips (this is required before this swapchain presents for the
+ * first time.
+ */
+ VkSwapchainKHR m_ancestor;
+
+ /**
+ * @brief Handle to the logical device the swapchain is created for.
+ */
+ VkDevice m_device;
+
+ /**
+ * @brief Handle to the queue used for signalling submissions
+ */
+ VkQueue m_queue;
+
+ /**
+ * @brief Return the VkAllocationCallbacks passed in this object constructor.
+ */
+ const VkAllocationCallbacks *get_allocation_callbacks()
+ {
+ return m_allocator.get_original_callbacks();
+ }
+
+ /**
+ * @brief Method to wait on all pending buffers to be displayed.
+ */
+ void wait_for_pending_buffers();
+
+ /**
+ * @brief Remove cached ancestor.
+ */
+ void clear_ancestor();
+
+ /**
+ * @brief Remove cached descendant.
+ */
+ void clear_descendant();
+
+ /**
+ * @brief Deprecate this swapchain.
+ *
+ * If an application replaces an old swapchain with a new one, the older swapchain
+ * needs to be deprecated. This method releases all the FREE images and sets the
+ * descendant of the swapchain. We do not need to care about images in other states
+ * at this point since they will be released by the page flip thread.
+ *
+ * @param descendant Handle to the descendant swapchain.
+ */
+ void deprecate(VkSwapchainKHR descendant);
+
+ /**
+ * @brief Platform specific initialization
+ */
+ virtual VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info) = 0;
+
+ /**
+ * @brief Base swapchain teardown.
+ *
+ * Even though the inheritance gives us a nice way to defer display specific allocation
+ * and presentation outside of the base class, it however robs the children classes - which
+ * also happen to do some of their state setting - the oppurtunity to do the last clean up
+ * call, as the base class' destructor is called at the end. This method provides a way to do it.
+ * The destructor is a virtual function and much of the swapchain teardown happens in this method
+ * which gets called from the child's destructor.
+ */
+ void teardown();
+
+ /**
+ * @brief Creates a new swapchain image.
+ *
+ * @param image_create_info Data to be used to create the image.
+ *
+ * @param image Handle to the image.
+ *
+ * @return If image creation is successful returns VK_SUCCESS, otherwise
+ * will return VK_ERROR_OUT_OF_DEVICE_MEMORY or VK_ERROR_INITIALIZATION_FAILED
+ * depending on the error that occured.
+ */
+ virtual VkResult create_image(const VkImageCreateInfo &image_create_info) = 0;
+
+ virtual VkResult acquire_image(uint32_t *image_index) = 0;
+
+ /**
+ * @brief Method to present and image
+ *
+ * @param pending_index Index of the pending image to be presented.
+ *
+ */
+ virtual void present_image(uint32_t pending_index) = 0;
+
+ /**
+ * @brief Transition a presented image to free.
+ *
+ * Called by swapchain implementation when a new image has been presented.
+ *
+ * @param presented_index Index of the image to be marked as free.
+ */
+ void unpresent_image(uint32_t presented_index);
+
+ /**
+ * @brief Method to release a swapchain image
+ *
+ * @param image Handle to the image about to be released.
+ */
+ virtual void destroy_image(void){};
+};
+
+} /* namespace wsi */
+
#define VK_USE_PLATFORM_WAYLAND_KHR 1
#include "swapchain.hpp"
-#include "swapchain_wl_helpers.hpp"
#include <cstring>
#include <cassert>
#include <climits>
#include <drm_fourcc.h>
-#include "util/drm/drm_utils.hpp"
-
#if VULKAN_WSI_DEBUG > 0
-#define WSI_PRINT_ERROR(...) fprintf(stderr, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
+#define WSI_PRINT_ERROR(fmt, ...) fprintf(stderr, "[%s:%d - %s]" fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#else
#define WSI_PRINT_ERROR(...) (void)0
#endif
namespace tizen
{
-struct swapchain::wayland_image_data
+struct swapchain::tizen_image_data
{
int buffer_fd;
+ tbm_surface_h tbm_buffer;
+
int stride;
uint32_t offset;
- wl_buffer *buffer;
VkDeviceMemory memory;
};
swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
: swapchain_base(dev_data, pAllocator)
- , m_display(nullptr)
- , m_surface(nullptr)
- , m_dmabuf_interface(nullptr)
- , m_surface_queue(nullptr)
- , m_buffer_queue(nullptr)
- , m_present_pending(false)
{
}
swapchain::~swapchain()
{
- //int res;
teardown();
- if (m_dmabuf_interface != nullptr)
- {
- zwp_linux_dmabuf_v1_destroy(m_dmabuf_interface);
- }
- /*
- res = wsialloc_delete(&m_wsi_allocator);
- if (res != 0)
- {
- WSI_PRINT_ERROR("error deleting the allocator: %d\n", res);
- }*/
- if (m_surface_queue != nullptr)
- {
- wl_event_queue_destroy(m_surface_queue);
- }
- if (m_buffer_queue != nullptr)
- {
- wl_event_queue_destroy(m_buffer_queue);
- }
+ destroy_image();
+ tpl_surface_destroy_swapchain(m_tpl_surface);
+ tpl_object_unreference((tpl_object_t *)m_tpl_surface);
+ tpl_object_unreference((tpl_object_t *)m_tpl_display);
}
-static void roundtrip_cb_done(void *data, wl_callback *cb, uint32_t cb_data)
+#define TBM_FORMAT_0 0
+#define RETURN_FORMAT(comp, opaque, pre, post, inherit) \
+ do { \
+ if (comp == VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) \
+ return TBM_FORMAT_##opaque; \
+ else if (comp == VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) \
+ return TBM_FORMAT_##pre; \
+ else if (comp == VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) \
+ return TBM_FORMAT_##post; \
+ else if (comp == VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) \
+ return TBM_FORMAT_##inherit; \
+ else \
+ return 0; \
+ } while (0)
+
+
+static inline tbm_format
+wsi_tizen_get_tbm_format(VkFormat format, VkCompositeAlphaFlagBitsKHR comp)
{
- (void)cb_data;
-
- bool *cb_recvd = reinterpret_cast<bool *>(data);
- assert(cb_recvd);
-
- *cb_recvd = true;
+ switch (format) {
+ /* 4 4 4 4 */
+ case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
+ RETURN_FORMAT(comp, RGBX4444, RGBA4444, 0, RGBA4444);
+ case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
+ RETURN_FORMAT(comp, BGRX4444, BGRA4444, 0, BGRA4444);
+ /* 5 6 5 */
+ case VK_FORMAT_R5G6B5_UNORM_PACK16:
+ RETURN_FORMAT(comp, RGB565, RGB565, RGB565, RGB565);
+ case VK_FORMAT_B5G6R5_UNORM_PACK16:
+ RETURN_FORMAT(comp, BGR565, BGR565, BGR565, BGR565);
+ /* 5 5 5 1 */
+ case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
+ RETURN_FORMAT(comp, RGBX5551, RGBA5551, 0, RGBA5551);
+ case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
+ RETURN_FORMAT(comp, BGRX5551, BGRA5551, 0, BGRA5551);
+ case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
+ RETURN_FORMAT(comp, XRGB1555, ARGB1555, 0, ARGB1555);
+ /* 8 8 8 */
+ case VK_FORMAT_R8G8B8_UNORM:
+ RETURN_FORMAT(comp, BGR888, BGR888, BGR888, BGR888);
+ case VK_FORMAT_B8G8R8_UNORM:
+ RETURN_FORMAT(comp, RGB888, RGB888, RGB888, RGB888);
+ /* 8 8 8 8 */
+ case VK_FORMAT_B8G8R8A8_UNORM:
+ RETURN_FORMAT(comp, XRGB8888, ARGB8888, 0, ARGB8888);
+ case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
+ RETURN_FORMAT(comp, XBGR8888, ABGR8888, 0, ABGR8888);
+ /* 2 10 10 10 */
+ case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
+ RETURN_FORMAT(comp, XRGB2101010, ARGB2101010, 0, ARGB2101010);
+ case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+ RETURN_FORMAT(comp, XBGR2101010, ABGR2101010, 0, ABGR2101010);
+ default:
+ break;
+ }
+
+ return 0;
}
-int swapchain::roundtrip()
+VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo)
{
- int res;
- const wl_callback_listener listener = { roundtrip_cb_done };
- bool cb_recvd = false;
+ VkIcdSurfaceWayland *vk_surf = reinterpret_cast<VkIcdSurfaceWayland *>(pSwapchainCreateInfo->surface);
+ tbm_format format;
+ int tpl_present_mode;
+ tpl_result_t res;
- wl_callback *cb = wl_display_sync(m_display);
- if (!cb)
- {
- WSI_PRINT_ERROR("failed to create wl_display::sync callback\n");
- res = -1;
- goto exit;
+ m_tpl_display = tpl_display_create(TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD, vk_surf->display);
+ if (m_tpl_display == NULL) {
+ WSI_PRINT_ERROR("create tpl display failed\n");
+ return VK_ERROR_INITIALIZATION_FAILED;
}
+ tpl_object_reference((tpl_object_t *)m_tpl_display);
- wl_proxy_set_queue((wl_proxy *)cb, m_surface_queue);
+ format = wsi_tizen_get_tbm_format(pSwapchainCreateInfo->imageFormat, pSwapchainCreateInfo->compositeAlpha);
+ m_tpl_surface = tpl_surface_get(m_tpl_display, vk_surf->surface);
+ if (m_tpl_surface == NULL)
+ m_tpl_surface = tpl_surface_create(m_tpl_display, vk_surf->surface, TPL_SURFACE_TYPE_WINDOW, format);
- res = wl_callback_add_listener(cb, &listener, &cb_recvd);
- if (res == -1)
- {
- WSI_PRINT_ERROR("error setting wl_display::sync callback listener\n");
- goto exit;
+ if (m_tpl_surface == NULL) {
+ WSI_PRINT_ERROR("create tpl surface failed\n");
+ return VK_ERROR_INITIALIZATION_FAILED;
}
+ tpl_object_reference((tpl_object_t *)m_tpl_surface);
- res = wl_display_flush(m_display);
- if (res == -1)
- {
- WSI_PRINT_ERROR("error performing a flush on the display\n");
- goto exit;
+ switch(pSwapchainCreateInfo->presentMode) {
+ case VK_PRESENT_MODE_IMMEDIATE_KHR:
+ tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_IMMEDIATE;
+ break;
+ case VK_PRESENT_MODE_MAILBOX_KHR:
+ tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_MAILBOX;
+ break;
+ case VK_PRESENT_MODE_FIFO_KHR:
+ tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_FIFO;
+ break;
+ case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
+ tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED;
+ break;
+ default:
+ WSI_PRINT_ERROR("unsupported present mode, presentMode[%d].", pSwapchainCreateInfo->presentMode);
+ return VK_ERROR_INITIALIZATION_FAILED;
}
- do
- {
- res = dispatch_queue(m_display, m_surface_queue, 1000);
- } while (res > 0 && !cb_recvd);
- if (res < 0)
- {
- WSI_PRINT_ERROR("error dispatching on the surface queue\n");
- goto exit;
- }
- else if (res == 0)
- {
- WSI_PRINT_ERROR("timeout waiting for roundtrip callback\n");
- goto exit;
+ res = tpl_surface_create_swapchain(m_tpl_surface, format,
+ pSwapchainCreateInfo->imageExtent.width, pSwapchainCreateInfo->imageExtent.height,
+ pSwapchainCreateInfo->minImageCount, tpl_present_mode);
+ if (res != TPL_ERROR_NONE) {
+ WSI_PRINT_ERROR("create swapchain failed, ret[%d].\n", res);
+ return VK_ERROR_INITIALIZATION_FAILED;
}
-exit:
- if (cb)
- {
- wl_callback_destroy(cb);
- }
- return res;
+ return VK_SUCCESS;
}
-struct display_queue
-{
- wl_display *display;
- wl_event_queue *queue;
-};
-
-VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo)
+VkResult swapchain::allocate_image(const VkImageCreateInfo &image_create_info, tizen_image_data *image_data,
+ VkImage *image)
{
- VkIcdSurfaceWayland *vk_surf = reinterpret_cast<VkIcdSurfaceWayland *>(pSwapchainCreateInfo->surface);
-
- m_display = vk_surf->display;
- m_surface = vk_surf->surface;
-#if 0
- m_surface_queue = wl_display_create_queue(m_display);
- if (m_surface_queue == nullptr)
- {
- WSI_PRINT_ERROR("Failed to create wl surface display_queue.\n");
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- m_buffer_queue = wl_display_create_queue(m_display);
- if (m_buffer_queue == nullptr)
- {
- WSI_PRINT_ERROR("Failed to create wl buffer display_queue.\n");
- return VK_ERROR_INITIALIZATION_FAILED;
- }
+ VkResult result = VK_SUCCESS;
- wl_registry *registry = wl_display_get_registry(m_display);
- if (registry == nullptr)
+ assert(image_data->stride >= 0);
+ VkSubresourceLayout image_layout = {};
+ image_layout.offset = image_data->offset;
+ image_layout.rowPitch = static_cast<uint32_t>(image_data->stride);
+ VkImageDrmFormatModifierExplicitCreateInfoEXT drm_mod_info = {};
+ drm_mod_info.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT;
+ drm_mod_info.pNext = image_create_info.pNext;
+ drm_mod_info.drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
+ drm_mod_info.drmFormatModifierPlaneCount = 1;
+ drm_mod_info.pPlaneLayouts = &image_layout;
+
+ VkExternalMemoryImageCreateInfoKHR external_info = {};
+ external_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
+ external_info.pNext = &drm_mod_info;
+ external_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
+
+ VkImageCreateInfo image_info = image_create_info;
+ image_info.pNext = &external_info;
+ image_info.tiling = VK_IMAGE_TILING_LINEAR;
+ result = m_device_data.disp.CreateImage(m_device, &image_info, get_allocation_callbacks(), image);
+ if (result != VK_SUCCESS)
{
- WSI_PRINT_ERROR("Failed to get wl display registry.\n");
- return VK_ERROR_INITIALIZATION_FAILED;
+ WSI_PRINT_ERROR("Image creation failed.\n");
+ return result;
}
- wl_proxy_set_queue((struct wl_proxy *)registry, m_surface_queue);
+ VkMemoryFdPropertiesKHR mem_props = {};
+ mem_props.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
- const wl_registry_listener registry_listener = { registry_handler };
- int res = wl_registry_add_listener(registry, ®istry_listener, &m_dmabuf_interface);
- if (res < 0)
+ result = m_device_data.disp.GetMemoryFdPropertiesKHR(m_device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ image_data->buffer_fd, &mem_props);
+ if (result != VK_SUCCESS)
{
- WSI_PRINT_ERROR("Failed to add registry listener.\n");
- return VK_ERROR_INITIALIZATION_FAILED;
+ WSI_PRINT_ERROR("Error querying Fd properties.\n");
+ return result;
}
- res = roundtrip();
- if (res < 0)
+ uint32_t mem_idx;
+ for (mem_idx = 0; mem_idx < VK_MAX_MEMORY_TYPES; mem_idx++)
{
- WSI_PRINT_ERROR("Roundtrip failed.\n");
- return VK_ERROR_INITIALIZATION_FAILED;
+ if (mem_props.memoryTypeBits & (1 << mem_idx))
+ {
+ break;
+ }
}
-
- /* we should have the dma_buf interface by now */
- assert(m_dmabuf_interface);
-
- wl_registry_destroy(registry);
-
- res = wsialloc_new(-1, &m_wsi_allocator);
- if (res != 0)
+ off_t dma_buf_size = lseek(image_data->buffer_fd, 0, SEEK_END);
+ if (dma_buf_size < 0)
{
- WSI_PRINT_ERROR("Failed to create wsi allocator.\n");
- return VK_ERROR_INITIALIZATION_FAILED;
+ WSI_PRINT_ERROR("Failed to get DMA Buf size.\n");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
}
-#endif
- return VK_SUCCESS;
-}
-static void create_succeeded(void *data, struct zwp_linux_buffer_params_v1 *params, struct wl_buffer *buffer)
-{
- struct wl_buffer **wayland_buffer = (struct wl_buffer **)data;
- *wayland_buffer = buffer;
-}
+ VkImportMemoryFdInfoKHR import_mem_info = {};
+ import_mem_info.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
+ import_mem_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
+ import_mem_info.fd = image_data->buffer_fd;
-static const struct zwp_linux_buffer_params_v1_listener params_listener = { create_succeeded, NULL };
+ VkMemoryAllocateInfo alloc_info = {};
+ alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ alloc_info.pNext = &import_mem_info;
+ alloc_info.allocationSize = static_cast<uint64_t>(dma_buf_size);
+ alloc_info.memoryTypeIndex = mem_idx;
-static void buffer_release(void *data, struct wl_buffer *wayl_buffer)
-{
- swapchain *sc = (swapchain *)data;
- sc->release_buffer(wayl_buffer);
-}
+ result = m_device_data.disp.AllocateMemory(m_device, &alloc_info, get_allocation_callbacks(), &image_data->memory);
-void swapchain::release_buffer(struct wl_buffer *wayl_buffer)
-{
- uint32_t i;
- for (i = 0; i < m_swapchain_images.size(); i++)
+ if (result != VK_SUCCESS)
{
- wayland_image_data *data;
- data = (wayland_image_data *)m_swapchain_images[i].data;
- if (data->buffer == wayl_buffer)
- {
- unpresent_image(i);
- break;
- }
+ WSI_PRINT_ERROR("Failed to import memory.\n");
+ return result;
}
+ result = m_device_data.disp.BindImageMemory(m_device, *image, image_data->memory, 0);
- /* check we found a buffer to unpresent */
- assert(i < m_swapchain_images.size());
+ return result;
}
-static struct wl_buffer_listener buffer_listener = { buffer_release };
-
-VkResult swapchain::allocate_image(const VkImageCreateInfo &image_create_info, wayland_image_data *image_data,
- VkImage *image)
+VkResult swapchain::create_image(const VkImageCreateInfo &image_create_info)
{
VkResult result = VK_SUCCESS;
-
- image_data->buffer = nullptr;
- image_data->buffer_fd = -1;
- image_data->memory = VK_NULL_HANDLE;
-
- VkExternalImageFormatPropertiesKHR external_props = {};
- external_props.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR;
-
- VkImageFormatProperties2KHR format_props = {};
- format_props.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR;
- format_props.pNext = &external_props;
- {
- VkPhysicalDeviceExternalImageFormatInfoKHR external_info = {};
- external_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR;
- external_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
-
- VkPhysicalDeviceImageDrmFormatModifierInfoEXT drm_mod_info = {};
- drm_mod_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT;
- drm_mod_info.pNext = &external_info;
- drm_mod_info.drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
- drm_mod_info.sharingMode = image_create_info.sharingMode;
- drm_mod_info.queueFamilyIndexCount = image_create_info.queueFamilyIndexCount;
- drm_mod_info.pQueueFamilyIndices = image_create_info.pQueueFamilyIndices;
-
- VkPhysicalDeviceImageFormatInfo2KHR info = {};
- info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR;
- info.pNext = &drm_mod_info;
- info.format = image_create_info.format;
- info.type = image_create_info.imageType;
- info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
- info.usage = image_create_info.usage;
- info.flags = image_create_info.flags;
-
- result = m_device_data.instance_data.disp.GetPhysicalDeviceImageFormatProperties2KHR(m_device_data.physical_device,
- &info, &format_props);
- }
- if (result != VK_SUCCESS)
- {
- WSI_PRINT_ERROR("Failed to get physical device format support.\n");
- return result;
- }
- if (format_props.imageFormatProperties.maxExtent.width < image_create_info.extent.width ||
- format_props.imageFormatProperties.maxExtent.height < image_create_info.extent.height ||
- format_props.imageFormatProperties.maxExtent.depth < image_create_info.extent.depth)
- {
- WSI_PRINT_ERROR("Physical device does not support required extent.\n");
+ tpl_result_t res;
+ tbm_surface_h *buffers;
+ int tbm_buf_cnt, i = 0;
+
+ res = tpl_surface_get_swapchain_buffers(m_tpl_surface, &buffers, &tbm_buf_cnt);
+ if (res == TPL_ERROR_OUT_OF_MEMORY)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ else if (res != TPL_ERROR_NONE)
return VK_ERROR_INITIALIZATION_FAILED;
- }
- if (format_props.imageFormatProperties.maxMipLevels < image_create_info.mipLevels ||
- format_props.imageFormatProperties.maxArrayLayers < image_create_info.arrayLayers)
- {
- WSI_PRINT_ERROR("Physical device does not support required array layers or mip levels.\n");
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- if ((format_props.imageFormatProperties.sampleCounts & image_create_info.samples) != image_create_info.samples)
- {
- WSI_PRINT_ERROR("Physical device does not support required sample count.\n");
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- if (external_props.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR)
- {
- /* TODO: Handle exportable images which use ICD allocated memory in preference to an external allocator. */
- }
- if (!(external_props.externalMemoryProperties.externalMemoryFeatures &
- VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR))
- {
- WSI_PRINT_ERROR("Export/Import not supported.\n");
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- else
- {
- /* TODO: Handle Dedicated allocation bit. */
- uint32_t fourcc = util::drm::vk_to_drm_format(image_create_info.format);
-/*
- int res =
- wsialloc_alloc(&m_wsi_allocator, fourcc, image_create_info.extent.width, image_create_info.extent.height,
- &image_data->stride, &image_data->buffer_fd, &image_data->offset, nullptr);
- if (res != 0)
- {
- WSI_PRINT_ERROR("Failed allocation of DMA Buffer.\n");
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
-*/
- {
- assert(image_data->stride >= 0);
- VkSubresourceLayout image_layout = {};
- image_layout.offset = image_data->offset;
- image_layout.rowPitch = static_cast<uint32_t>(image_data->stride);
- VkImageDrmFormatModifierExplicitCreateInfoEXT drm_mod_info = {};
- drm_mod_info.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT;
- drm_mod_info.pNext = image_create_info.pNext;
- drm_mod_info.drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
- drm_mod_info.drmFormatModifierPlaneCount = 1;
- drm_mod_info.pPlaneLayouts = &image_layout;
-
- VkExternalMemoryImageCreateInfoKHR external_info = {};
- external_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
- external_info.pNext = &drm_mod_info;
- external_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
-
- VkImageCreateInfo image_info = image_create_info;
- image_info.pNext = &external_info;
- image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
- result = m_device_data.disp.CreateImage(m_device, &image_info, get_allocation_callbacks(), image);
- }
- if (result != VK_SUCCESS)
+ if (!m_swapchain_images.try_resize(tbm_buf_cnt))
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ i = 0;
+ for (auto &image: m_swapchain_images) {
+ tizen_image_data *image_data = nullptr;
+ if (get_allocation_callbacks() != nullptr)
{
- WSI_PRINT_ERROR("Image creation failed.\n");
- return result;
+ image_data = static_cast<tizen_image_data *>(
+ get_allocation_callbacks()->pfnAllocation(get_allocation_callbacks()->pUserData, sizeof(tizen_image_data),
+ alignof(tizen_image_data), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ } else {
+ image_data = static_cast<tizen_image_data *>(malloc(sizeof(tizen_image_data)));
}
- {
- VkMemoryFdPropertiesKHR mem_props = {};
- mem_props.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
-
- result = m_device_data.disp.GetMemoryFdPropertiesKHR(m_device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
- image_data->buffer_fd, &mem_props);
- if (result != VK_SUCCESS)
- {
- WSI_PRINT_ERROR("Error querying Fd properties.\n");
- return result;
- }
- uint32_t mem_idx;
- for (mem_idx = 0; mem_idx < VK_MAX_MEMORY_TYPES; mem_idx++)
- {
- if (mem_props.memoryTypeBits & (1 << mem_idx))
- {
- break;
- }
- }
- off_t dma_buf_size = lseek(image_data->buffer_fd, 0, SEEK_END);
- if (dma_buf_size < 0)
- {
- WSI_PRINT_ERROR("Failed to get DMA Buf size.\n");
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
+ tbm_surface_info_s info;
+ tbm_bo bo = tbm_surface_internal_get_bo(buffers[i], 0);
+ tbm_bo_handle bo_handle = tbm_bo_get_handle(bo, TBM_DEVICE_3D);
+ tbm_surface_get_info(buffers[i], &info);
- VkImportMemoryFdInfoKHR import_mem_info = {};
- import_mem_info.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
- import_mem_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
- import_mem_info.fd = image_data->buffer_fd;
+ image_data->tbm_buffer = buffers[i];
+ image_data->buffer_fd = bo_handle.u32;
+ image_data->stride = info.planes[0].stride;
+ image_data->offset = info.planes[0].offset;
+ image_data->memory = VK_NULL_HANDLE;
- VkMemoryAllocateInfo alloc_info = {};
- alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- alloc_info.pNext = &import_mem_info;
- alloc_info.allocationSize = static_cast<uint64_t>(dma_buf_size);
- alloc_info.memoryTypeIndex = mem_idx;
+ image.data = static_cast<void *>(image_data);
- result = m_device_data.disp.AllocateMemory(m_device, &alloc_info, get_allocation_callbacks(), &image_data->memory);
- }
+ result = allocate_image(image_create_info, image_data, &image.image);
if (result != VK_SUCCESS)
{
- WSI_PRINT_ERROR("Failed to import memory.\n");
- return result;
+ WSI_PRINT_ERROR("Failed to allocate image.\n");
+ goto out;
}
- result = m_device_data.disp.BindImageMemory(m_device, *image, image_data->memory, 0);
- }
-
- return result;
-}
-VkResult swapchain::create_image(const VkImageCreateInfo &image_create_info, swapchain_image &image)
-{
- uint32_t fourcc = util::drm::vk_to_drm_format(image_create_info.format);
+ /* Initialize presentation fence. */
+ VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0 };
+ result = m_device_data.disp.CreateFence(m_device, &fenceInfo, get_allocation_callbacks(), &image.present_fence);
- int res;
- VkResult result = VK_SUCCESS;
-
- wayland_image_data *image_data = nullptr;
- VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, 0 };
-
- /* Create image_data */
- if (get_allocation_callbacks() != nullptr)
- {
- image_data = static_cast<wayland_image_data *>(
- get_allocation_callbacks()->pfnAllocation(get_allocation_callbacks()->pUserData, sizeof(wayland_image_data),
- alignof(wayland_image_data), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
- }
- else
- {
- image_data = static_cast<wayland_image_data *>(malloc(sizeof(wayland_image_data)));
- }
- if (image_data == nullptr)
- {
- result = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto out;
+ i++;
}
- image.data = reinterpret_cast<void *>(image_data);
- image.status = swapchain_image::FREE;
- result = allocate_image(image_create_info, image_data, &image.image);
- if (result != VK_SUCCESS)
- {
- WSI_PRINT_ERROR("Failed to allocate image.\n");
- goto out;
- }
-
- /* create a wl_buffer using the dma_buf protocol */
- struct zwp_linux_buffer_params_v1 *params;
- params = zwp_linux_dmabuf_v1_create_params(m_dmabuf_interface);
- zwp_linux_buffer_params_v1_add(params, image_data->buffer_fd, 0, image_data->offset, image_data->stride, 0, 0);
- wl_proxy_set_queue((struct wl_proxy *)params, m_surface_queue);
- res = zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, &image_data->buffer);
- if (res < 0)
- {
- result = VK_ERROR_INITIALIZATION_FAILED;
- goto out;
- }
- zwp_linux_buffer_params_v1_create(params, image_create_info.extent.width, image_create_info.extent.height, fourcc,
- 0);
-
- /* TODO: don't roundtrip - we should be able to send the create request now,
- * and only wait for it on first present. only do this once, not for all buffers created */
- res = roundtrip();
- if (res < 0)
- {
- result = VK_ERROR_INITIALIZATION_FAILED;
- goto out;
- }
+ return VK_SUCCESS;
- /* should now have a wl_buffer */
- assert(image_data->buffer);
- zwp_linux_buffer_params_v1_destroy(params);
- wl_proxy_set_queue((struct wl_proxy *)image_data->buffer, m_buffer_queue);
- res = wl_buffer_add_listener(image_data->buffer, &buffer_listener, this);
- if (res < 0)
- {
- result = VK_ERROR_INITIALIZATION_FAILED;
- goto out;
- }
+out:
- /* Initialize presentation fence. */
- result = m_device_data.disp.CreateFence(m_device, &fenceInfo, get_allocation_callbacks(), &image.present_fence);
+ destroy_image();
-out:
- if (result != VK_SUCCESS)
- {
- destroy_image(image);
- return result;
- }
return result;
}
-static void frame_done(void *data, wl_callback *cb, uint32_t cb_data)
+VkResult swapchain::acquire_image(uint32_t *image_index)
{
- (void)cb_data;
+ tbm_surface_h tbm_buf = tpl_surface_dequeue_buffer_with_sync(m_tpl_surface, UINT64_MAX, NULL);
- bool *present_pending = reinterpret_cast<bool *>(data);
- assert(present_pending);
+ if (tbm_buf == NULL)
+ return VK_ERROR_SURFACE_LOST_KHR;
- *present_pending = false;
+ for (unsigned int i = 0; i < m_swapchain_images.size(); i++) {
+ tizen_image_data *image_data = reinterpret_cast<tizen_image_data *>(m_swapchain_images[i].data);
+ if (image_data->tbm_buffer == tbm_buf) {
+ *image_index = i;
+ return VK_SUCCESS;
+ }
+ }
- wl_callback_destroy(cb);
+ return VK_ERROR_SURFACE_LOST_KHR;
}
void swapchain::present_image(uint32_t pendingIndex)
{
- int res;
- wayland_image_data *image_data = reinterpret_cast<wayland_image_data *>(m_swapchain_images[pendingIndex].data);
- /* if a frame is already pending, wait for a hint to present again */
- if (m_present_pending)
- {
- assert(m_present_mode == VK_PRESENT_MODE_FIFO_KHR);
- do
- {
- /* block waiting for the compositor to return the wl_surface::frame
- * callback. We may want to change this to timeout after a period of
- * time if the compositor isn't responding (perhaps because the
- * window is hidden).
- */
- res = dispatch_queue(m_display, m_surface_queue, -1);
- } while (res > 0 && m_present_pending);
-
- if (res <= 0)
- {
- WSI_PRINT_ERROR("error waiting for Wayland compositor frame hint\n");
- m_is_valid = false;
- /* try to present anyway */
- }
- }
-
- wl_surface_attach(m_surface, image_data->buffer, 0, 0);
- /* TODO: work out damage */
- wl_surface_damage(m_surface, 0, 0, INT32_MAX, INT32_MAX);
-
- if (m_present_mode == VK_PRESENT_MODE_FIFO_KHR)
- {
- /* request a hint when we can present the _next_ frame */
- wl_callback *cb = wl_surface_frame(m_surface);
- if (cb)
- {
- wl_proxy_set_queue((wl_proxy *)cb, m_surface_queue);
- static const wl_callback_listener frame_listener = { frame_done };
- m_present_pending = true;
- wl_callback_add_listener(cb, &frame_listener, &m_present_pending);
- }
- }
- else
- {
- assert(m_present_mode == VK_PRESENT_MODE_MAILBOX_KHR);
- /* weston only _queues_ wl_buffer::release events. This means when the
- * compositor flushes the client it only sends the events if some other events
- * have been posted.
- *
- * As such we have to request a sync callback - we discard it straight away
- * as we don't actually need the callback, but it means the
- * wl_buffer::release event is actually sent.
- */
- wl_callback *cb = wl_display_sync(m_display);
- assert(cb);
- if (cb)
- {
- wl_callback_destroy(cb);
- }
- }
-
- wl_surface_commit(m_surface);
- res = wl_display_flush(m_display);
- if (res < 0)
- {
- WSI_PRINT_ERROR("error flushing the display\n");
- /* Setting the swapchain as invalid */
- m_is_valid = false;
- }
+ tizen_image_data *image_data = reinterpret_cast<tizen_image_data *>(m_swapchain_images[pendingIndex].data);
+ tpl_surface_enqueue_buffer_with_damage_and_sync(m_tpl_surface, image_data->tbm_buffer, 0, NULL, -1);
}
-void swapchain::destroy_image(swapchain_image &image)
+void swapchain::destroy_image(void)
{
- if (image.status != swapchain_image::INVALID)
- {
+ for (auto &image: m_swapchain_images) {
if (image.present_fence != VK_NULL_HANDLE)
{
m_device_data.disp.DestroyFence(m_device, image.present_fence, get_allocation_callbacks());
image.present_fence = VK_NULL_HANDLE;
}
-
if (image.image != VK_NULL_HANDLE)
{
m_device_data.disp.DestroyImage(m_device, image.image, get_allocation_callbacks());
image.image = VK_NULL_HANDLE;
}
- }
- if (image.data != nullptr)
- {
- auto image_data = reinterpret_cast<wayland_image_data *>(image.data);
- if (image_data->buffer != nullptr)
- {
- wl_buffer_destroy(image_data->buffer);
- }
- if (image_data->memory != VK_NULL_HANDLE)
- {
- m_device_data.disp.FreeMemory(m_device, image_data->memory, get_allocation_callbacks());
- }
- else if (image_data->buffer_fd >= 0)
- {
- close(image_data->buffer_fd);
- }
-
- if (get_allocation_callbacks() != nullptr)
+ if (image.data != nullptr)
{
- get_allocation_callbacks()->pfnFree(get_allocation_callbacks()->pUserData, image_data);
- }
- else
- {
- free(image_data);
- }
- image.data = nullptr;
- }
-
- image.status = swapchain_image::INVALID;
-}
-
-bool swapchain::free_image_found()
-{
- for (auto &img : m_swapchain_images)
- {
- if (img.status == swapchain_image::FREE)
- {
- return true;
- }
- }
- return false;
-}
-
-VkResult swapchain::get_free_buffer(uint64_t *timeout)
-{
- int ms_timeout, res;
-
- if (*timeout >= INT_MAX * 1000llu * 1000llu)
- {
- ms_timeout = INT_MAX;
- }
- else
- {
- ms_timeout = *timeout / 1000llu / 1000llu;
- }
-
- /* The current dispatch_queue implementation will return if any
- * events are returned, even if no events are dispatched to the buffer
- * queue. Therefore dispatch repeatedly until a buffer has been freed.
- */
- do
- {
- res = dispatch_queue(m_display, m_buffer_queue, ms_timeout);
- } while (!free_image_found() && res > 0);
-
- if (res > 0)
- {
- *timeout = 0;
- return VK_SUCCESS;
- }
- else if (res == 0)
- {
- if (*timeout == 0)
- {
- return VK_NOT_READY;
- }
- else
- {
- return VK_TIMEOUT;
+ tizen_image_data *image_data = reinterpret_cast<tizen_image_data *>(image.data);
+ if (image_data->memory != VK_NULL_HANDLE)
+ {
+ m_device_data.disp.FreeMemory(m_device, image_data->memory, get_allocation_callbacks());
+ }
+ else if (image_data->buffer_fd >= 0)
+ {
+ close(image_data->buffer_fd);
+ }
+ if (get_allocation_callbacks() != nullptr)
+ {
+ get_allocation_callbacks()->pfnFree(get_allocation_callbacks()->pUserData, image_data);
+ }
+ else
+ {
+ free(image_data);
+ }
+ image.data = nullptr;
}
}
- else
- {
- return VK_ERROR_DEVICE_LOST;
- }
}
} // namespace wayland