Files
third_party_mesa3d/src/vulkan/x11.c

287 lines
9.2 KiB
C
Raw Normal View History

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_surface *surface;
2015-05-15 22:04:52 -07:00
struct anv_device_memory *memory;
anv_image_create((VkDevice) device,
&(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
surface = &image->primary_surface;
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,
surface->stride, I915_TILING_X);
2015-05-15 22:04:52 -07:00
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,
surface->stride,
2015-05-15 22:04:52 -07:00
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;
}