vk: Prefix most filenames with anv
[mesa.git] / src / vulkan / anv_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 "anv_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
52 if (pData == NULL) {
53 *pDataSize = size;
54 return VK_SUCCESS;
55 }
56
57 if (*pDataSize < size)
58 return vk_error(VK_ERROR_INVALID_VALUE);
59
60 *pDataSize = size;
61
62 for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++)
63 properties[i].swapChainFormat = formats[i];
64
65 return VK_SUCCESS;
66
67 default:
68 return VK_UNSUPPORTED;
69 }
70 }
71
72 struct anv_swap_chain {
73 struct anv_device * device;
74 xcb_connection_t * conn;
75 xcb_window_t window;
76 xcb_gc_t gc;
77 VkExtent2D extent;
78 uint32_t count;
79 struct {
80 struct anv_image * image;
81 struct anv_device_memory * memory;
82 xcb_pixmap_t pixmap;
83 } images[0];
84 };
85
86 VkResult anv_CreateSwapChainWSI(
87 VkDevice _device,
88 const VkSwapChainCreateInfoWSI* pCreateInfo,
89 VkSwapChainWSI* pSwapChain)
90 {
91 ANV_FROM_HANDLE(anv_device, device, _device);
92
93 struct anv_swap_chain *chain;
94 xcb_void_cookie_t cookie;
95 VkResult result;
96 size_t size;
97 int ret;
98
99 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
100
101 size = sizeof(*chain) + pCreateInfo->imageCount * sizeof(chain->images[0]);
102 chain = anv_device_alloc(device, size, 8,
103 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
104 if (chain == NULL)
105 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
106
107 chain->device = device;
108 chain->conn = (xcb_connection_t *) pCreateInfo->pNativeWindowSystemHandle;
109 chain->window = (xcb_window_t) (uintptr_t) pCreateInfo->pNativeWindowHandle;
110 chain->count = pCreateInfo->imageCount;
111 chain->extent = pCreateInfo->imageExtent;
112
113 for (uint32_t i = 0; i < chain->count; i++) {
114 VkDeviceMemory memory_h;
115 VkImage image_h;
116 struct anv_image *image;
117 struct anv_surface *surface;
118 struct anv_device_memory *memory;
119
120 anv_image_create(_device,
121 &(struct anv_image_create_info) {
122 .force_tile_mode = true,
123 .tile_mode = XMAJOR,
124 .vk_info =
125 &(VkImageCreateInfo) {
126 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
127 .imageType = VK_IMAGE_TYPE_2D,
128 .format = pCreateInfo->imageFormat,
129 .extent = {
130 .width = pCreateInfo->imageExtent.width,
131 .height = pCreateInfo->imageExtent.height,
132 .depth = 1
133 },
134 .mipLevels = 1,
135 .arraySize = 1,
136 .samples = 1,
137 /* FIXME: Need a way to use X tiling to allow scanout */
138 .tiling = VK_IMAGE_TILING_OPTIMAL,
139 .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
140 .flags = 0,
141 }},
142 &image_h);
143
144 image = anv_image_from_handle(image_h);
145 surface = &image->primary_surface;
146
147 anv_AllocMemory(_device,
148 &(VkMemoryAllocInfo) {
149 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
150 .allocationSize = image->size,
151 .memoryTypeIndex = 0,
152 },
153 &memory_h);
154
155 memory = anv_device_memory_from_handle(memory_h);
156
157 anv_BindImageMemory(VK_NULL_HANDLE, anv_image_to_handle(image),
158 memory_h, 0);
159
160 ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
161 surface->stride, I915_TILING_X);
162 if (ret) {
163 result = vk_error(VK_ERROR_UNKNOWN);
164 goto fail;
165 }
166
167 int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
168 if (fd == -1) {
169 result = vk_error(VK_ERROR_UNKNOWN);
170 goto fail;
171 }
172
173 uint32_t bpp = 32;
174 uint32_t depth = 24;
175 xcb_pixmap_t pixmap = xcb_generate_id(chain->conn);
176
177 cookie =
178 xcb_dri3_pixmap_from_buffer_checked(chain->conn,
179 pixmap,
180 chain->window,
181 image->size,
182 pCreateInfo->imageExtent.width,
183 pCreateInfo->imageExtent.height,
184 surface->stride,
185 depth, bpp, fd);
186
187 chain->images[i].image = image;
188 chain->images[i].memory = memory;
189 chain->images[i].pixmap = pixmap;
190 image->swap_chain = chain;
191
192 xcb_discard_reply(chain->conn, cookie.sequence);
193 }
194
195 chain->gc = xcb_generate_id(chain->conn);
196 if (!chain->gc) {
197 result = vk_error(VK_ERROR_UNKNOWN);
198 goto fail;
199 }
200
201 cookie = xcb_create_gc(chain->conn,
202 chain->gc,
203 chain->window,
204 XCB_GC_GRAPHICS_EXPOSURES,
205 (uint32_t []) { 0 });
206 xcb_discard_reply(chain->conn, cookie.sequence);
207
208 *pSwapChain = anv_swap_chain_to_handle(chain);
209
210 return VK_SUCCESS;
211
212 fail:
213 return result;
214 }
215
216 VkResult anv_DestroySwapChainWSI(
217 VkSwapChainWSI _chain)
218 {
219 ANV_FROM_HANDLE(anv_swap_chain, chain, _chain);
220
221 anv_device_free(chain->device, chain);
222
223 return VK_SUCCESS;
224 }
225
226 VkResult anv_GetSwapChainInfoWSI(
227 VkSwapChainWSI _chain,
228 VkSwapChainInfoTypeWSI infoType,
229 size_t* pDataSize,
230 void* pData)
231 {
232 ANV_FROM_HANDLE(anv_swap_chain, chain, _chain);
233
234 VkSwapChainImageInfoWSI *images;
235 size_t size;
236
237 switch (infoType) {
238 case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
239 size = sizeof(*images) * chain->count;
240 if (pData && *pDataSize < size)
241 return VK_ERROR_INVALID_VALUE;
242
243 *pDataSize = size;
244 if (!pData)
245 return VK_SUCCESS;
246
247 images = pData;
248 for (uint32_t i = 0; i < chain->count; i++) {
249 images[i].image = anv_image_to_handle(chain->images[i].image);
250 images[i].memory = anv_device_memory_to_handle(chain->images[i].memory);
251 }
252
253 return VK_SUCCESS;
254
255 default:
256 return VK_UNSUPPORTED;
257 }
258 }
259
260 VkResult anv_QueuePresentWSI(
261 VkQueue queue_,
262 const VkPresentInfoWSI* pPresentInfo)
263 {
264 ANV_FROM_HANDLE(anv_image, image, pPresentInfo->image);
265
266 struct anv_swap_chain *chain = image->swap_chain;
267 xcb_void_cookie_t cookie;
268 xcb_pixmap_t pixmap;
269
270 assert(pPresentInfo->sType == VK_STRUCTURE_TYPE_PRESENT_INFO_WSI);
271
272 if (chain == NULL)
273 return vk_error(VK_ERROR_INVALID_VALUE);
274
275 pixmap = XCB_NONE;
276 for (uint32_t i = 0; i < chain->count; i++) {
277 if (image == chain->images[i].image) {
278 pixmap = chain->images[i].pixmap;
279 break;
280 }
281 }
282
283 if (pixmap == XCB_NONE)
284 return vk_error(VK_ERROR_INVALID_VALUE);
285
286 cookie = xcb_copy_area(chain->conn,
287 pixmap,
288 chain->window,
289 chain->gc,
290 0, 0,
291 0, 0,
292 chain->extent.width,
293 chain->extent.height);
294 xcb_discard_reply(chain->conn, cookie.sequence);
295
296 xcb_flush(chain->conn);
297
298 return VK_SUCCESS;
299 }