vk/formats: Don't abbreviate tokens in the format table
[mesa.git] / src / vulkan / x11.c
1 /*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "private.h"
25
26 #include <xcb/xcb.h>
27 #include <xcb/dri3.h>
28 #include <xcb/present.h>
29
30 static const VkFormat formats[] = {
31 VK_FORMAT_B5G6R5_UNORM,
32 VK_FORMAT_B8G8R8A8_UNORM,
33 VK_FORMAT_B8G8R8A8_SRGB,
34 };
35
36 VkResult anv_GetDisplayInfoWSI(
37 VkDisplayWSI display,
38 VkDisplayInfoTypeWSI infoType,
39 size_t* pDataSize,
40 void* pData)
41 {
42 VkDisplayFormatPropertiesWSI *properties = pData;
43 size_t size;
44
45 if (pDataSize == NULL)
46 return VK_ERROR_INVALID_POINTER;
47
48 switch (infoType) {
49 case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI:
50 size = sizeof(properties[0]) * ARRAY_SIZE(formats);
51 if (pData && *pDataSize < size)
52 return vk_error(VK_ERROR_INVALID_VALUE);
53
54 *pDataSize = size;
55 for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++)
56 properties[i].swapChainFormat = formats[i];
57
58 return VK_SUCCESS;
59
60 default:
61 return VK_UNSUPPORTED;
62 }
63 }
64
65 struct anv_swap_chain {
66 struct anv_device * device;
67 xcb_connection_t * conn;
68 xcb_window_t window;
69 xcb_gc_t gc;
70 VkExtent2D extent;
71 uint32_t count;
72 struct {
73 struct anv_image * image;
74 struct anv_device_memory * memory;
75 xcb_pixmap_t pixmap;
76 } images[0];
77 };
78
79 VkResult anv_CreateSwapChainWSI(
80 VkDevice _device,
81 const VkSwapChainCreateInfoWSI* pCreateInfo,
82 VkSwapChainWSI* pSwapChain)
83 {
84 struct anv_device *device = (struct anv_device *) _device;
85 struct anv_swap_chain *chain;
86 xcb_void_cookie_t cookie;
87 VkResult result;
88 size_t size;
89 int ret;
90
91 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
92
93 size = sizeof(*chain) + pCreateInfo->imageCount * sizeof(chain->images[0]);
94 chain = anv_device_alloc(device, size, 8,
95 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
96 if (chain == NULL)
97 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
98
99 chain->device = device;
100 chain->conn = (xcb_connection_t *) pCreateInfo->pNativeWindowSystemHandle;
101 chain->window = (xcb_window_t) (uintptr_t) pCreateInfo->pNativeWindowHandle;
102 chain->count = pCreateInfo->imageCount;
103 chain->extent = pCreateInfo->imageExtent;
104
105 for (uint32_t i = 0; i < chain->count; i++) {
106 struct anv_image *image;
107 struct anv_device_memory *memory;
108
109 anv_image_create((VkDevice) device,
110 &(VkImageCreateInfo) {
111 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
112 .imageType = VK_IMAGE_TYPE_2D,
113 .format = pCreateInfo->imageFormat,
114 .extent = {
115 .width = pCreateInfo->imageExtent.width,
116 .height = pCreateInfo->imageExtent.height,
117 .depth = 1
118 },
119 .mipLevels = 1,
120 .arraySize = 1,
121 .samples = 1,
122 /* FIXME: Need a way to use X tiling to allow scanout */
123 .tiling = VK_IMAGE_TILING_OPTIMAL,
124 .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
125 .flags = 0,
126 },
127 &(struct anv_image_create_info) {
128 .tile_mode = XMAJOR
129 },
130 (VkImage *) &image);
131
132 anv_AllocMemory((VkDevice) device,
133 &(VkMemoryAllocInfo) {
134 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
135 .allocationSize = image->size,
136 },
137 (VkDeviceMemory *) &memory);
138
139 anv_QueueBindObjectMemory(VK_NULL_HANDLE,
140 VK_OBJECT_TYPE_IMAGE,
141 (VkImage) image, 0,
142 (VkDeviceMemory) memory, 0);
143
144 ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
145 image->stride, I915_TILING_X);
146 if (ret) {
147 result = vk_error(VK_ERROR_UNKNOWN);
148 goto fail;
149 }
150
151 int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
152 if (fd == -1) {
153 result = vk_error(VK_ERROR_UNKNOWN);
154 goto fail;
155 }
156
157 uint32_t bpp = 32;
158 uint32_t depth = 24;
159 xcb_pixmap_t pixmap = xcb_generate_id(chain->conn);
160
161 cookie =
162 xcb_dri3_pixmap_from_buffer_checked(chain->conn,
163 pixmap,
164 chain->window,
165 image->size,
166 pCreateInfo->imageExtent.width,
167 pCreateInfo->imageExtent.height,
168 image->stride,
169 depth, bpp, fd);
170
171 chain->images[i].image = image;
172 chain->images[i].memory = memory;
173 chain->images[i].pixmap = pixmap;
174 image->swap_chain = chain;
175
176 xcb_discard_reply(chain->conn, cookie.sequence);
177 }
178
179 chain->gc = xcb_generate_id(chain->conn);
180 if (!chain->gc) {
181 result = vk_error(VK_ERROR_UNKNOWN);
182 goto fail;
183 }
184
185 cookie = xcb_create_gc(chain->conn,
186 chain->gc,
187 chain->window,
188 XCB_GC_GRAPHICS_EXPOSURES,
189 (uint32_t []) { 0 });
190 xcb_discard_reply(chain->conn, cookie.sequence);
191
192 *pSwapChain = (VkSwapChainWSI) chain;
193
194 return VK_SUCCESS;
195
196 fail:
197 return result;
198 }
199
200 VkResult anv_DestroySwapChainWSI(
201 VkSwapChainWSI swapChain)
202 {
203 struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
204 struct anv_device *device = chain->device;
205
206 anv_device_free(device, chain);
207
208 return VK_SUCCESS;
209 }
210
211 VkResult anv_GetSwapChainInfoWSI(
212 VkSwapChainWSI swapChain,
213 VkSwapChainInfoTypeWSI infoType,
214 size_t* pDataSize,
215 void* pData)
216 {
217 struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
218 VkSwapChainImageInfoWSI *images;
219 size_t size;
220
221 switch (infoType) {
222 case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
223 size = sizeof(*images) * chain->count;
224 if (pData && *pDataSize < size)
225 return VK_ERROR_INVALID_VALUE;
226
227 *pDataSize = size;
228 if (!pData)
229 return VK_SUCCESS;
230
231 images = pData;
232 for (uint32_t i = 0; i < chain->count; i++) {
233 images[i].image = (VkImage) chain->images[i].image;
234 images[i].memory = (VkDeviceMemory) chain->images[i].memory;
235 }
236
237 return VK_SUCCESS;
238
239 default:
240 return VK_UNSUPPORTED;
241 }
242 }
243
244 VkResult anv_QueuePresentWSI(
245 VkQueue queue_,
246 const VkPresentInfoWSI* pPresentInfo)
247 {
248 struct anv_image *image = (struct anv_image *) pPresentInfo->image;
249 struct anv_swap_chain *chain = image->swap_chain;
250 xcb_void_cookie_t cookie;
251 xcb_pixmap_t pixmap;
252
253 assert(pPresentInfo->sType == VK_STRUCTURE_TYPE_PRESENT_INFO_WSI);
254
255 if (chain == NULL)
256 return vk_error(VK_ERROR_INVALID_VALUE);
257
258 pixmap = XCB_NONE;
259 for (uint32_t i = 0; i < chain->count; i++) {
260 if ((VkImage) chain->images[i].image == pPresentInfo->image) {
261 pixmap = chain->images[i].pixmap;
262 break;
263 }
264 }
265
266 if (pixmap == XCB_NONE)
267 return vk_error(VK_ERROR_INVALID_VALUE);
268
269 cookie = xcb_copy_area(chain->conn,
270 pixmap,
271 chain->window,
272 chain->gc,
273 0, 0,
274 0, 0,
275 chain->extent.width,
276 chain->extent.height);
277 xcb_discard_reply(chain->conn, cookie.sequence);
278
279 xcb_flush(chain->conn);
280
281 return VK_SUCCESS;
282 }