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 VkFormat formats
[] = {
31 VK_FORMAT_B5G6R5_UNORM
,
32 VK_FORMAT_B8G8R8A8_UNORM
,
33 VK_FORMAT_B8G8R8A8_SRGB
,
36 static const VkSurfacePresentModePropertiesWSI present_modes
[] = {
37 { VK_PRESENT_MODE_MAILBOX_WSI
},
41 x11_get_window_supported(struct anv_wsi_implementation
*impl
,
42 struct anv_physical_device
*physical_device
,
43 const VkSurfaceDescriptionWindowWSI
*window
,
47 stub_return(VK_SUCCESS
);
51 x11_get_surface_info(struct anv_wsi_implementation
*impl
,
52 struct anv_device
*device
,
53 VkSurfaceDescriptionWindowWSI
*vk_window
,
54 VkSurfaceInfoTypeWSI infoType
,
55 size_t* pDataSize
, void* pData
)
57 if (pDataSize
== NULL
)
58 return vk_error(VK_ERROR_INVALID_POINTER
);
61 case VK_SURFACE_INFO_TYPE_PROPERTIES_WSI
: {
62 VkSurfacePropertiesWSI
*props
= pData
;
65 *pDataSize
= sizeof(*props
);
69 assert(*pDataSize
>= sizeof(*props
));
71 VkPlatformHandleXcbWSI
*vk_xcb_handle
= vk_window
->pPlatformHandle
;
72 xcb_connection_t
*conn
= vk_xcb_handle
->connection
;
73 xcb_window_t win
= (xcb_window_t
)(uintptr_t)vk_window
->pPlatformWindow
;
75 xcb_get_geometry_cookie_t cookie
= xcb_get_geometry(conn
, win
);
76 xcb_get_geometry_reply_t
*geom
= xcb_get_geometry_reply(conn
, cookie
,
78 VkExtent2D extent
= { geom
->width
, geom
->height
};
81 props
->minImageCount
= 2;
82 props
->maxImageCount
= 4;
83 props
->currentExtent
= extent
;
84 props
->minImageExtent
= extent
;
85 props
->maxImageExtent
= extent
;
86 props
->supportedTransforms
= VK_SURFACE_TRANSFORM_NONE_BIT_WSI
;
87 props
->currentTransform
= VK_SURFACE_TRANSFORM_NONE_WSI
;
88 props
->maxImageArraySize
= 1;
89 props
->supportedUsageFlags
=
90 VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT
|
91 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
96 case VK_SURFACE_INFO_TYPE_FORMATS_WSI
:
98 *pDataSize
= sizeof(formats
);
102 assert(*pDataSize
>= sizeof(formats
));
103 memcpy(pData
, formats
, *pDataSize
);
107 case VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI
:
109 *pDataSize
= sizeof(present_modes
);
113 assert(*pDataSize
>= sizeof(present_modes
));
114 memcpy(pData
, present_modes
, *pDataSize
);
118 return vk_error(VK_ERROR_INVALID_VALUE
);
123 struct anv_image
* image
;
124 struct anv_device_memory
* memory
;
126 xcb_get_geometry_cookie_t geom_cookie
;
130 struct x11_swap_chain
{
131 struct anv_swap_chain base
;
133 xcb_connection_t
* conn
;
137 uint32_t image_count
;
139 struct x11_image images
[0];
143 x11_get_swap_chain_info(struct anv_swap_chain
*anv_chain
,
144 VkSwapChainInfoTypeWSI infoType
,
145 size_t* pDataSize
, void* pData
)
147 struct x11_swap_chain
*chain
= (struct x11_swap_chain
*)anv_chain
;
151 case VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI
: {
152 VkSwapChainImagePropertiesWSI
*images
= pData
;
154 size
= chain
->image_count
* sizeof(*images
);
161 assert(size
<= *pDataSize
);
162 for (uint32_t i
= 0; i
< chain
->image_count
; i
++)
163 images
[i
].image
= anv_image_to_handle(chain
->images
[i
].image
);
171 return vk_error(VK_ERROR_INVALID_VALUE
);
176 x11_acquire_next_image(struct anv_swap_chain
*anv_chain
,
178 VkSemaphore semaphore
,
179 uint32_t *image_index
)
181 struct x11_swap_chain
*chain
= (struct x11_swap_chain
*)anv_chain
;
182 struct x11_image
*image
= &chain
->images
[chain
->next_image
];
185 xcb_get_geometry_reply_t
*geom
=
186 xcb_get_geometry_reply(chain
->conn
, image
->geom_cookie
, NULL
);
189 if (geom
->width
!= chain
->extent
.width
||
190 geom
->height
!= chain
->extent
.height
) {
192 return VK_ERROR_OUT_OF_DATE_WSI
;
197 *image_index
= chain
->next_image
;
198 chain
->next_image
= (chain
->next_image
+ 1) % chain
->image_count
;
203 x11_queue_present(struct anv_swap_chain
*anv_chain
,
204 struct anv_queue
*queue
,
205 uint32_t image_index
)
207 struct x11_swap_chain
*chain
= (struct x11_swap_chain
*)anv_chain
;
208 struct x11_image
*image
= &chain
->images
[image_index
];
210 assert(image_index
< chain
->image_count
);
212 xcb_void_cookie_t cookie
;
214 cookie
= xcb_copy_area(chain
->conn
,
221 chain
->extent
.height
);
222 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
224 image
->geom_cookie
= xcb_get_geometry(chain
->conn
, chain
->window
);
227 xcb_flush(chain
->conn
);
233 x11_destroy_swap_chain(struct anv_swap_chain
*anv_chain
)
235 struct x11_swap_chain
*chain
= (struct x11_swap_chain
*)anv_chain
;
236 xcb_void_cookie_t cookie
;
238 for (uint32_t i
= 0; i
< chain
->image_count
; i
++) {
239 struct x11_image
*image
= &chain
->images
[i
];
242 xcb_discard_reply(chain
->conn
, image
->geom_cookie
.sequence
);
244 cookie
= xcb_free_pixmap(chain
->conn
, image
->pixmap
);
245 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
247 /* TODO: Delete images and free memory */
250 anv_device_free(chain
->base
.device
, chain
);
256 x11_create_swap_chain(struct anv_wsi_implementation
*impl
,
257 struct anv_device
*device
,
258 const VkSwapChainCreateInfoWSI
*pCreateInfo
,
259 struct anv_swap_chain
**swap_chain_out
)
261 struct x11_swap_chain
*chain
;
262 xcb_void_cookie_t cookie
;
265 assert(pCreateInfo
->pSurfaceDescription
->sType
==
266 VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI
);
267 VkSurfaceDescriptionWindowWSI
*vk_window
=
268 (VkSurfaceDescriptionWindowWSI
*)pCreateInfo
->pSurfaceDescription
;
269 assert(vk_window
->platform
== VK_PLATFORM_XCB_WSI
);
271 int num_images
= pCreateInfo
->minImageCount
;
273 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI
);
275 size_t size
= sizeof(*chain
) + num_images
* sizeof(chain
->images
[0]);
276 chain
= anv_device_alloc(device
, size
, 8,
277 VK_SYSTEM_ALLOC_TYPE_API_OBJECT
);
279 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
281 chain
->base
.device
= device
;
282 chain
->base
.destroy
= x11_destroy_swap_chain
;
283 chain
->base
.get_swap_chain_info
= x11_get_swap_chain_info
;
284 chain
->base
.acquire_next_image
= x11_acquire_next_image
;
285 chain
->base
.queue_present
= x11_queue_present
;
287 VkPlatformHandleXcbWSI
*vk_xcb_handle
= vk_window
->pPlatformHandle
;
289 chain
->conn
= (xcb_connection_t
*) vk_xcb_handle
->connection
;
290 chain
->window
= (xcb_window_t
) (uintptr_t)vk_window
->pPlatformWindow
;
291 chain
->extent
= pCreateInfo
->imageExtent
;
292 chain
->image_count
= num_images
;
293 chain
->next_image
= 0;
295 for (uint32_t i
= 0; i
< chain
->image_count
; i
++) {
296 VkDeviceMemory memory_h
;
298 struct anv_image
*image
;
299 struct anv_surface
*surface
;
300 struct anv_device_memory
*memory
;
302 anv_image_create(anv_device_to_handle(device
),
303 &(struct anv_image_create_info
) {
304 .force_tile_mode
= true,
308 &(VkImageCreateInfo
) {
309 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
310 .imageType
= VK_IMAGE_TYPE_2D
,
311 .format
= pCreateInfo
->imageFormat
,
313 .width
= pCreateInfo
->imageExtent
.width
,
314 .height
= pCreateInfo
->imageExtent
.height
,
320 /* FIXME: Need a way to use X tiling to allow scanout */
321 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
322 .usage
= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
,
327 image
= anv_image_from_handle(image_h
);
328 assert(anv_format_is_color(image
->format
));
330 surface
= &image
->color_surface
;
332 anv_AllocMemory(anv_device_to_handle(device
),
333 &(VkMemoryAllocInfo
) {
334 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO
,
335 .allocationSize
= image
->size
,
336 .memoryTypeIndex
= 0,
340 memory
= anv_device_memory_from_handle(memory_h
);
342 anv_BindImageMemory(VK_NULL_HANDLE
, anv_image_to_handle(image
),
345 int ret
= anv_gem_set_tiling(device
, memory
->bo
.gem_handle
,
346 surface
->stride
, I915_TILING_X
);
348 result
= vk_errorf(VK_ERROR_UNKNOWN
, "set_tiling failed: %m");
352 int fd
= anv_gem_handle_to_fd(device
, memory
->bo
.gem_handle
);
354 result
= vk_errorf(VK_ERROR_UNKNOWN
, "handle_to_fd failed: %m");
360 xcb_pixmap_t pixmap
= xcb_generate_id(chain
->conn
);
363 xcb_dri3_pixmap_from_buffer_checked(chain
->conn
,
367 pCreateInfo
->imageExtent
.width
,
368 pCreateInfo
->imageExtent
.height
,
372 chain
->images
[i
].image
= image
;
373 chain
->images
[i
].memory
= memory
;
374 chain
->images
[i
].pixmap
= pixmap
;
375 chain
->images
[i
].busy
= false;
377 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
380 chain
->gc
= xcb_generate_id(chain
->conn
);
382 result
= vk_error(VK_ERROR_UNKNOWN
);
386 cookie
= xcb_create_gc(chain
->conn
,
389 XCB_GC_GRAPHICS_EXPOSURES
,
390 (uint32_t []) { 0 });
391 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
393 *swap_chain_out
= &chain
->base
;
402 anv_x11_init_wsi(struct anv_instance
*instance
)
404 struct anv_wsi_implementation
*impl
;
406 impl
= anv_instance_alloc(instance
, sizeof(*impl
), 8,
407 VK_SYSTEM_ALLOC_TYPE_INTERNAL
);
409 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
411 impl
->get_window_supported
= x11_get_window_supported
;
412 impl
->get_surface_info
= x11_get_surface_info
;
413 impl
->create_swap_chain
= x11_create_swap_chain
;
415 instance
->wsi_impl
[VK_PLATFORM_XCB_WSI
] = impl
;
421 anv_x11_finish_wsi(struct anv_instance
*instance
)
423 anv_instance_free(instance
, instance
->wsi_impl
[VK_PLATFORM_XCB_WSI
]);