2 * Copyright © 2015 Intel Corporation
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:
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
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
26 #include <xcb/present.h>
30 static const VkSurfaceFormatKHR formats
[] = {
31 { .format
= VK_FORMAT_B8G8R8A8_UNORM
, },
34 static const VkPresentModeKHR present_modes
[] = {
35 VK_PRESENT_MODE_MAILBOX_KHR
,
39 x11_get_window_supported(struct anv_wsi_implementation
*impl
,
40 struct anv_physical_device
*physical_device
,
41 const VkSurfaceDescriptionWindowKHR
*window
,
45 stub_return(VK_SUCCESS
);
49 x11_get_surface_properties(struct anv_wsi_implementation
*impl
,
50 struct anv_device
*device
,
51 const VkSurfaceDescriptionWindowKHR
*vk_window
,
52 VkSurfacePropertiesKHR
*props
)
54 VkPlatformHandleXcbKHR
*vk_xcb_handle
= vk_window
->pPlatformHandle
;
55 xcb_connection_t
*conn
= vk_xcb_handle
->connection
;
56 xcb_window_t win
= *(xcb_window_t
*)vk_window
->pPlatformWindow
;
58 xcb_get_geometry_cookie_t cookie
= xcb_get_geometry(conn
, win
);
59 xcb_generic_error_t
*err
;
60 xcb_get_geometry_reply_t
*geom
= xcb_get_geometry_reply(conn
, cookie
,
64 VkExtent2D extent
= { geom
->width
, geom
->height
};
65 props
->currentExtent
= extent
;
66 props
->minImageExtent
= extent
;
67 props
->maxImageExtent
= extent
;
69 /* This can happen if the client didn't wait for the configure event
70 * to come back from the compositor. In that case, we don't know the
71 * size of the window so we just return valid "I don't know" stuff.
74 props
->currentExtent
= (VkExtent2D
) { -1, -1 };
75 props
->minImageExtent
= (VkExtent2D
) { 1, 1 };
76 props
->maxImageExtent
= (VkExtent2D
) { INT16_MAX
, INT16_MAX
};
79 props
->minImageCount
= 2;
80 props
->maxImageCount
= 4;
81 props
->supportedTransforms
= VK_SURFACE_TRANSFORM_NONE_BIT_KHR
;
82 props
->currentTransform
= VK_SURFACE_TRANSFORM_NONE_KHR
;
83 props
->maxImageArraySize
= 1;
84 props
->supportedUsageFlags
=
85 VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT
|
86 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
92 x11_get_surface_formats(struct anv_wsi_implementation
*impl
,
93 struct anv_device
*device
,
94 const VkSurfaceDescriptionWindowKHR
*vk_window
,
95 uint32_t *pCount
, VkSurfaceFormatKHR
*pSurfaceFormats
)
97 if (pSurfaceFormats
== NULL
) {
98 *pCount
= ARRAY_SIZE(formats
);
102 assert(*pCount
>= ARRAY_SIZE(formats
));
103 typed_memcpy(pSurfaceFormats
, formats
, *pCount
);
104 *pCount
= ARRAY_SIZE(formats
);
110 x11_get_surface_present_modes(struct anv_wsi_implementation
*impl
,
111 struct anv_device
*device
,
112 const VkSurfaceDescriptionWindowKHR
*vk_window
,
113 uint32_t *pCount
, VkPresentModeKHR
*pPresentModes
)
115 if (pPresentModes
== NULL
) {
116 *pCount
= ARRAY_SIZE(present_modes
);
120 assert(*pCount
>= ARRAY_SIZE(present_modes
));
121 typed_memcpy(pPresentModes
, present_modes
, *pCount
);
122 *pCount
= ARRAY_SIZE(present_modes
);
128 struct anv_image
* image
;
129 struct anv_device_memory
* memory
;
131 xcb_get_geometry_cookie_t geom_cookie
;
135 struct x11_swapchain
{
136 struct anv_swapchain base
;
138 xcb_connection_t
* conn
;
142 uint32_t image_count
;
144 struct x11_image images
[0];
148 x11_get_images(struct anv_swapchain
*anv_chain
,
149 uint32_t* pCount
, VkImage
*pSwapchainImages
)
151 struct x11_swapchain
*chain
= (struct x11_swapchain
*)anv_chain
;
153 if (pSwapchainImages
== NULL
) {
154 *pCount
= chain
->image_count
;
158 assert(chain
->image_count
<= *pCount
);
159 for (uint32_t i
= 0; i
< chain
->image_count
; i
++)
160 pSwapchainImages
[i
] = anv_image_to_handle(chain
->images
[i
].image
);
162 *pCount
= chain
->image_count
;
168 x11_acquire_next_image(struct anv_swapchain
*anv_chain
,
170 VkSemaphore semaphore
,
171 uint32_t *image_index
)
173 struct x11_swapchain
*chain
= (struct x11_swapchain
*)anv_chain
;
174 struct x11_image
*image
= &chain
->images
[chain
->next_image
];
177 xcb_generic_error_t
*err
;
178 xcb_get_geometry_reply_t
*geom
=
179 xcb_get_geometry_reply(chain
->conn
, image
->geom_cookie
, &err
);
182 return vk_error(VK_ERROR_OUT_OF_DATE_KHR
);
185 if (geom
->width
!= chain
->extent
.width
||
186 geom
->height
!= chain
->extent
.height
) {
188 return vk_error(VK_ERROR_OUT_OF_DATE_KHR
);
195 *image_index
= chain
->next_image
;
196 chain
->next_image
= (chain
->next_image
+ 1) % chain
->image_count
;
201 x11_queue_present(struct anv_swapchain
*anv_chain
,
202 struct anv_queue
*queue
,
203 uint32_t image_index
)
205 struct x11_swapchain
*chain
= (struct x11_swapchain
*)anv_chain
;
206 struct x11_image
*image
= &chain
->images
[image_index
];
208 assert(image_index
< chain
->image_count
);
210 xcb_void_cookie_t cookie
;
212 cookie
= xcb_copy_area(chain
->conn
,
219 chain
->extent
.height
);
220 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
222 image
->geom_cookie
= xcb_get_geometry(chain
->conn
, chain
->window
);
225 xcb_flush(chain
->conn
);
231 x11_destroy_swapchain(struct anv_swapchain
*anv_chain
)
233 struct x11_swapchain
*chain
= (struct x11_swapchain
*)anv_chain
;
234 xcb_void_cookie_t cookie
;
236 for (uint32_t i
= 0; i
< chain
->image_count
; i
++) {
237 struct x11_image
*image
= &chain
->images
[i
];
240 xcb_discard_reply(chain
->conn
, image
->geom_cookie
.sequence
);
242 cookie
= xcb_free_pixmap(chain
->conn
, image
->pixmap
);
243 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
245 /* TODO: Delete images and free memory */
248 anv_device_free(chain
->base
.device
, chain
);
254 x11_create_swapchain(struct anv_wsi_implementation
*impl
,
255 struct anv_device
*device
,
256 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
257 struct anv_swapchain
**swapchain_out
)
259 struct x11_swapchain
*chain
;
260 xcb_void_cookie_t cookie
;
263 assert(pCreateInfo
->pSurfaceDescription
->sType
==
264 VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR
);
265 VkSurfaceDescriptionWindowKHR
*vk_window
=
266 (VkSurfaceDescriptionWindowKHR
*)pCreateInfo
->pSurfaceDescription
;
267 assert(vk_window
->platform
== VK_PLATFORM_XCB_KHR
);
269 int num_images
= pCreateInfo
->minImageCount
;
271 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
);
273 size_t size
= sizeof(*chain
) + num_images
* sizeof(chain
->images
[0]);
274 chain
= anv_device_alloc(device
, size
, 8,
275 VK_SYSTEM_ALLOC_TYPE_API_OBJECT
);
277 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
279 chain
->base
.device
= device
;
280 chain
->base
.destroy
= x11_destroy_swapchain
;
281 chain
->base
.get_images
= x11_get_images
;
282 chain
->base
.acquire_next_image
= x11_acquire_next_image
;
283 chain
->base
.queue_present
= x11_queue_present
;
285 VkPlatformHandleXcbKHR
*vk_xcb_handle
= vk_window
->pPlatformHandle
;
287 chain
->conn
= (xcb_connection_t
*) vk_xcb_handle
->connection
;
288 chain
->window
= *(xcb_window_t
*)vk_window
->pPlatformWindow
;
289 chain
->extent
= pCreateInfo
->imageExtent
;
290 chain
->image_count
= num_images
;
291 chain
->next_image
= 0;
293 for (uint32_t i
= 0; i
< chain
->image_count
; i
++) {
294 VkDeviceMemory memory_h
;
296 struct anv_image
*image
;
297 struct anv_surface
*surface
;
298 struct anv_device_memory
*memory
;
300 anv_image_create(anv_device_to_handle(device
),
301 &(struct anv_image_create_info
) {
302 .force_tiling
= true,
303 .tiling
= ISL_TILING_X
,
306 &(VkImageCreateInfo
) {
307 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
308 .imageType
= VK_IMAGE_TYPE_2D
,
309 .format
= pCreateInfo
->imageFormat
,
311 .width
= pCreateInfo
->imageExtent
.width
,
312 .height
= pCreateInfo
->imageExtent
.height
,
318 /* FIXME: Need a way to use X tiling to allow scanout */
319 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
320 .usage
= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
,
325 image
= anv_image_from_handle(image_h
);
326 assert(anv_format_is_color(image
->format
));
328 surface
= &image
->color_surface
;
330 anv_AllocMemory(anv_device_to_handle(device
),
331 &(VkMemoryAllocInfo
) {
332 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO
,
333 .allocationSize
= image
->size
,
334 .memoryTypeIndex
= 0,
338 memory
= anv_device_memory_from_handle(memory_h
);
340 anv_BindImageMemory(VK_NULL_HANDLE
, anv_image_to_handle(image
),
343 int ret
= anv_gem_set_tiling(device
, memory
->bo
.gem_handle
,
344 surface
->stride
, I915_TILING_X
);
346 /* FINISHME: Choose a better error. */
347 result
= vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY
,
348 "set_tiling failed: %m");
352 int fd
= anv_gem_handle_to_fd(device
, memory
->bo
.gem_handle
);
354 /* FINISHME: Choose a better error. */
355 result
= vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY
,
356 "handle_to_fd failed: %m");
362 xcb_pixmap_t pixmap
= xcb_generate_id(chain
->conn
);
365 xcb_dri3_pixmap_from_buffer_checked(chain
->conn
,
369 pCreateInfo
->imageExtent
.width
,
370 pCreateInfo
->imageExtent
.height
,
374 chain
->images
[i
].image
= image
;
375 chain
->images
[i
].memory
= memory
;
376 chain
->images
[i
].pixmap
= pixmap
;
377 chain
->images
[i
].busy
= false;
379 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
382 chain
->gc
= xcb_generate_id(chain
->conn
);
384 /* FINISHME: Choose a better error. */
385 result
= vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
389 cookie
= xcb_create_gc(chain
->conn
,
392 XCB_GC_GRAPHICS_EXPOSURES
,
393 (uint32_t []) { 0 });
394 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
396 *swapchain_out
= &chain
->base
;
405 anv_x11_init_wsi(struct anv_instance
*instance
)
407 struct anv_wsi_implementation
*impl
;
409 impl
= anv_instance_alloc(instance
, sizeof(*impl
), 8,
410 VK_SYSTEM_ALLOC_TYPE_INTERNAL
);
412 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
414 impl
->get_window_supported
= x11_get_window_supported
;
415 impl
->get_surface_properties
= x11_get_surface_properties
;
416 impl
->get_surface_formats
= x11_get_surface_formats
;
417 impl
->get_surface_present_modes
= x11_get_surface_present_modes
;
418 impl
->create_swapchain
= x11_create_swapchain
;
420 instance
->wsi_impl
[VK_PLATFORM_XCB_KHR
] = impl
;
426 anv_x11_finish_wsi(struct anv_instance
*instance
)
428 anv_instance_free(instance
, instance
->wsi_impl
[VK_PLATFORM_XCB_KHR
]);