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