2015-05-15 22:04:52 -07:00
|
|
|
/*
|
|
|
|
* Copyright © 2015 Intel Corporation
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "private.h"
|
|
|
|
|
|
|
|
#include <xcb/xcb.h>
|
|
|
|
#include <xcb/dri3.h>
|
|
|
|
#include <xcb/present.h>
|
|
|
|
|
|
|
|
static const VkFormat formats[] = {
|
|
|
|
VK_FORMAT_B5G6R5_UNORM,
|
|
|
|
VK_FORMAT_B8G8R8A8_UNORM,
|
|
|
|
VK_FORMAT_B8G8R8A8_SRGB,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkResult anv_GetDisplayInfoWSI(
|
|
|
|
VkDisplayWSI display,
|
|
|
|
VkDisplayInfoTypeWSI infoType,
|
|
|
|
size_t* pDataSize,
|
|
|
|
void* pData)
|
|
|
|
{
|
|
|
|
VkDisplayFormatPropertiesWSI *properties = pData;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
if (pDataSize == NULL)
|
|
|
|
return VK_ERROR_INVALID_POINTER;
|
|
|
|
|
|
|
|
switch (infoType) {
|
|
|
|
case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI:
|
|
|
|
size = sizeof(properties[0]) * ARRAY_SIZE(formats);
|
|
|
|
if (pData && *pDataSize < size)
|
|
|
|
return vk_error(VK_ERROR_INVALID_VALUE);
|
|
|
|
|
|
|
|
*pDataSize = size;
|
|
|
|
for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++)
|
|
|
|
properties[i].swapChainFormat = formats[i];
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return VK_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct anv_swap_chain {
|
|
|
|
struct anv_device * device;
|
|
|
|
xcb_connection_t * conn;
|
|
|
|
xcb_window_t window;
|
|
|
|
xcb_gc_t gc;
|
|
|
|
VkExtent2D extent;
|
|
|
|
uint32_t count;
|
|
|
|
struct {
|
|
|
|
struct anv_image * image;
|
|
|
|
struct anv_device_memory * memory;
|
|
|
|
xcb_pixmap_t pixmap;
|
|
|
|
} images[0];
|
|
|
|
};
|
|
|
|
|
|
|
|
VkResult anv_CreateSwapChainWSI(
|
|
|
|
VkDevice _device,
|
|
|
|
const VkSwapChainCreateInfoWSI* pCreateInfo,
|
|
|
|
VkSwapChainWSI* pSwapChain)
|
|
|
|
{
|
|
|
|
struct anv_device *device = (struct anv_device *) _device;
|
|
|
|
struct anv_swap_chain *chain;
|
|
|
|
xcb_void_cookie_t cookie;
|
|
|
|
VkResult result;
|
|
|
|
size_t size;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
|
|
|
|
|
|
|
|
size = sizeof(*chain) + pCreateInfo->imageCount * sizeof(chain->images[0]);
|
|
|
|
chain = anv_device_alloc(device, size, 8,
|
|
|
|
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
|
|
|
if (chain == NULL)
|
|
|
|
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
chain->device = device;
|
|
|
|
chain->conn = (xcb_connection_t *) pCreateInfo->pNativeWindowSystemHandle;
|
|
|
|
chain->window = (xcb_window_t) (uintptr_t) pCreateInfo->pNativeWindowHandle;
|
|
|
|
chain->count = pCreateInfo->imageCount;
|
|
|
|
chain->extent = pCreateInfo->imageExtent;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < chain->count; i++) {
|
|
|
|
struct anv_image *image;
|
|
|
|
struct anv_device_memory *memory;
|
|
|
|
|
|
|
|
anv_image_create((VkDevice) device,
|
2015-06-26 20:06:08 -07:00
|
|
|
&(struct anv_image_create_info) {
|
|
|
|
.force_tile_mode = true,
|
|
|
|
.tile_mode = XMAJOR,
|
|
|
|
.vk_info =
|
|
|
|
&(VkImageCreateInfo) {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
|
|
.imageType = VK_IMAGE_TYPE_2D,
|
|
|
|
.format = pCreateInfo->imageFormat,
|
|
|
|
.extent = {
|
|
|
|
.width = pCreateInfo->imageExtent.width,
|
|
|
|
.height = pCreateInfo->imageExtent.height,
|
|
|
|
.depth = 1
|
|
|
|
},
|
|
|
|
.mipLevels = 1,
|
|
|
|
.arraySize = 1,
|
|
|
|
.samples = 1,
|
|
|
|
/* FIXME: Need a way to use X tiling to allow scanout */
|
|
|
|
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
|
|
|
.flags = 0,
|
|
|
|
}},
|
|
|
|
(VkImage *) &image);
|
2015-05-15 22:04:52 -07:00
|
|
|
|
|
|
|
anv_AllocMemory((VkDevice) device,
|
|
|
|
&(VkMemoryAllocInfo) {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
|
|
|
|
.allocationSize = image->size,
|
|
|
|
},
|
|
|
|
(VkDeviceMemory *) &memory);
|
|
|
|
|
|
|
|
anv_QueueBindObjectMemory(VK_NULL_HANDLE,
|
|
|
|
VK_OBJECT_TYPE_IMAGE,
|
|
|
|
(VkImage) image, 0,
|
|
|
|
(VkDeviceMemory) memory, 0);
|
|
|
|
|
|
|
|
ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
|
|
|
|
image->stride, I915_TILING_X);
|
|
|
|
if (ret) {
|
|
|
|
result = vk_error(VK_ERROR_UNKNOWN);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
|
|
|
|
if (fd == -1) {
|
|
|
|
result = vk_error(VK_ERROR_UNKNOWN);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t bpp = 32;
|
|
|
|
uint32_t depth = 24;
|
|
|
|
xcb_pixmap_t pixmap = xcb_generate_id(chain->conn);
|
|
|
|
|
|
|
|
cookie =
|
|
|
|
xcb_dri3_pixmap_from_buffer_checked(chain->conn,
|
|
|
|
pixmap,
|
|
|
|
chain->window,
|
|
|
|
image->size,
|
|
|
|
pCreateInfo->imageExtent.width,
|
|
|
|
pCreateInfo->imageExtent.height,
|
|
|
|
image->stride,
|
|
|
|
depth, bpp, fd);
|
|
|
|
|
|
|
|
chain->images[i].image = image;
|
|
|
|
chain->images[i].memory = memory;
|
|
|
|
chain->images[i].pixmap = pixmap;
|
|
|
|
image->swap_chain = chain;
|
|
|
|
|
|
|
|
xcb_discard_reply(chain->conn, cookie.sequence);
|
|
|
|
}
|
|
|
|
|
|
|
|
chain->gc = xcb_generate_id(chain->conn);
|
|
|
|
if (!chain->gc) {
|
|
|
|
result = vk_error(VK_ERROR_UNKNOWN);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
cookie = xcb_create_gc(chain->conn,
|
|
|
|
chain->gc,
|
|
|
|
chain->window,
|
|
|
|
XCB_GC_GRAPHICS_EXPOSURES,
|
|
|
|
(uint32_t []) { 0 });
|
|
|
|
xcb_discard_reply(chain->conn, cookie.sequence);
|
|
|
|
|
|
|
|
*pSwapChain = (VkSwapChainWSI) chain;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult anv_DestroySwapChainWSI(
|
|
|
|
VkSwapChainWSI swapChain)
|
|
|
|
{
|
|
|
|
struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
|
|
|
|
struct anv_device *device = chain->device;
|
|
|
|
|
|
|
|
anv_device_free(device, chain);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult anv_GetSwapChainInfoWSI(
|
|
|
|
VkSwapChainWSI swapChain,
|
|
|
|
VkSwapChainInfoTypeWSI infoType,
|
|
|
|
size_t* pDataSize,
|
|
|
|
void* pData)
|
|
|
|
{
|
|
|
|
struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
|
|
|
|
VkSwapChainImageInfoWSI *images;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
switch (infoType) {
|
|
|
|
case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
|
|
|
|
size = sizeof(*images) * chain->count;
|
|
|
|
if (pData && *pDataSize < size)
|
|
|
|
return VK_ERROR_INVALID_VALUE;
|
|
|
|
|
|
|
|
*pDataSize = size;
|
|
|
|
if (!pData)
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
images = pData;
|
|
|
|
for (uint32_t i = 0; i < chain->count; i++) {
|
|
|
|
images[i].image = (VkImage) chain->images[i].image;
|
|
|
|
images[i].memory = (VkDeviceMemory) chain->images[i].memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return VK_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult anv_QueuePresentWSI(
|
|
|
|
VkQueue queue_,
|
|
|
|
const VkPresentInfoWSI* pPresentInfo)
|
|
|
|
{
|
|
|
|
struct anv_image *image = (struct anv_image *) pPresentInfo->image;
|
|
|
|
struct anv_swap_chain *chain = image->swap_chain;
|
|
|
|
xcb_void_cookie_t cookie;
|
|
|
|
xcb_pixmap_t pixmap;
|
|
|
|
|
|
|
|
assert(pPresentInfo->sType == VK_STRUCTURE_TYPE_PRESENT_INFO_WSI);
|
|
|
|
|
|
|
|
if (chain == NULL)
|
|
|
|
return vk_error(VK_ERROR_INVALID_VALUE);
|
|
|
|
|
|
|
|
pixmap = XCB_NONE;
|
|
|
|
for (uint32_t i = 0; i < chain->count; i++) {
|
|
|
|
if ((VkImage) chain->images[i].image == pPresentInfo->image) {
|
|
|
|
pixmap = chain->images[i].pixmap;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pixmap == XCB_NONE)
|
|
|
|
return vk_error(VK_ERROR_INVALID_VALUE);
|
|
|
|
|
|
|
|
cookie = xcb_copy_area(chain->conn,
|
|
|
|
pixmap,
|
|
|
|
chain->window,
|
|
|
|
chain->gc,
|
|
|
|
0, 0,
|
|
|
|
0, 0,
|
|
|
|
chain->extent.width,
|
|
|
|
chain->extent.height);
|
|
|
|
xcb_discard_reply(chain->conn, cookie.sequence);
|
|
|
|
|
|
|
|
xcb_flush(chain->conn);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|