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>
31 struct anv_wsi_surface base
;
33 xcb_connection_t
*connection
;
37 static const VkSurfaceFormatKHR formats
[] = {
38 { .format
= VK_FORMAT_B8G8R8A8_UNORM
, },
41 static const VkPresentModeKHR present_modes
[] = {
42 VK_PRESENT_MODE_MAILBOX_KHR
,
45 VkBool32
anv_GetPhysicalDeviceXcbPresentationSupportKHR(
46 VkPhysicalDevice physicalDevice
,
47 uint32_t queueFamilyIndex
,
48 xcb_connection_t
* connection
,
49 xcb_visualid_t visual_id
)
51 anv_finishme("Check that we actually have DRI3");
56 x11_surface_get_capabilities(struct anv_wsi_surface
*wsi_surface
,
57 struct anv_physical_device
*device
,
58 VkSurfaceCapabilitiesKHR
*caps
)
60 struct x11_surface
*surface
= (struct x11_surface
*)wsi_surface
;
62 xcb_get_geometry_cookie_t cookie
= xcb_get_geometry(surface
->connection
,
64 xcb_generic_error_t
*err
;
65 xcb_get_geometry_reply_t
*geom
= xcb_get_geometry_reply(surface
->connection
,
68 VkExtent2D extent
= { geom
->width
, geom
->height
};
69 caps
->currentExtent
= extent
;
70 caps
->minImageExtent
= extent
;
71 caps
->maxImageExtent
= extent
;
73 /* This can happen if the client didn't wait for the configure event
74 * to come back from the compositor. In that case, we don't know the
75 * size of the window so we just return valid "I don't know" stuff.
77 caps
->currentExtent
= (VkExtent2D
) { -1, -1 };
78 caps
->minImageExtent
= (VkExtent2D
) { 1, 1 };
79 caps
->maxImageExtent
= (VkExtent2D
) { INT16_MAX
, INT16_MAX
};
84 caps
->minImageCount
= 2;
85 caps
->maxImageCount
= 4;
86 caps
->supportedTransforms
= VK_SURFACE_TRANSFORM_NONE_BIT_KHR
;
87 caps
->currentTransform
= VK_SURFACE_TRANSFORM_NONE_BIT_KHR
;
88 caps
->maxImageArrayLayers
= 1;
89 caps
->supportedCompositeAlpha
= VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
;
90 caps
->supportedUsageFlags
=
91 VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
92 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
98 x11_surface_get_formats(struct anv_wsi_surface
*surface
,
99 struct anv_physical_device
*device
,
100 uint32_t *pSurfaceFormatCount
,
101 VkSurfaceFormatKHR
*pSurfaceFormats
)
103 if (pSurfaceFormats
== NULL
) {
104 *pSurfaceFormatCount
= ARRAY_SIZE(formats
);
108 assert(*pSurfaceFormatCount
>= ARRAY_SIZE(formats
));
109 typed_memcpy(pSurfaceFormats
, formats
, *pSurfaceFormatCount
);
110 *pSurfaceFormatCount
= ARRAY_SIZE(formats
);
116 x11_surface_get_present_modes(struct anv_wsi_surface
*surface
,
117 struct anv_physical_device
*device
,
118 uint32_t *pPresentModeCount
,
119 VkPresentModeKHR
*pPresentModes
)
121 if (pPresentModes
== NULL
) {
122 *pPresentModeCount
= ARRAY_SIZE(present_modes
);
126 assert(*pPresentModeCount
>= ARRAY_SIZE(present_modes
));
127 typed_memcpy(pPresentModes
, present_modes
, *pPresentModeCount
);
128 *pPresentModeCount
= ARRAY_SIZE(present_modes
);
134 x11_surface_destroy(struct anv_wsi_surface
*surface
,
135 const VkAllocationCallbacks
*pAllocator
)
137 anv_free2(&surface
->instance
->alloc
, pAllocator
, surface
);
141 x11_surface_create_swapchain(struct anv_wsi_surface
*surface
,
142 struct anv_device
*device
,
143 const VkSwapchainCreateInfoKHR
* pCreateInfo
,
144 const VkAllocationCallbacks
* pAllocator
,
145 struct anv_swapchain
**swapchain
);
147 VkResult
anv_CreateXcbSurfaceKHR(
148 VkInstance _instance
,
149 xcb_connection_t
* connection
,
151 const VkAllocationCallbacks
* pAllocator
,
152 VkSurfaceKHR
* pSurface
)
154 ANV_FROM_HANDLE(anv_instance
, instance
, _instance
);
155 struct x11_surface
*surface
;
157 surface
= anv_alloc2(&instance
->alloc
, pAllocator
, sizeof *surface
, 8,
158 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
160 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
162 surface
->connection
= connection
;
163 surface
->window
= window
;
165 surface
->base
.instance
= instance
;
166 surface
->base
.destroy
= x11_surface_destroy
;
167 surface
->base
.get_capabilities
= x11_surface_get_capabilities
;
168 surface
->base
.get_formats
= x11_surface_get_formats
;
169 surface
->base
.get_present_modes
= x11_surface_get_present_modes
;
170 surface
->base
.create_swapchain
= x11_surface_create_swapchain
;
172 *pSurface
= anv_wsi_surface_to_handle(&surface
->base
);
178 struct anv_image
* image
;
179 struct anv_device_memory
* memory
;
181 xcb_get_geometry_cookie_t geom_cookie
;
185 struct x11_swapchain
{
186 struct anv_swapchain base
;
188 xcb_connection_t
* conn
;
192 uint32_t image_count
;
194 struct x11_image images
[0];
198 x11_get_images(struct anv_swapchain
*anv_chain
,
199 uint32_t* pCount
, VkImage
*pSwapchainImages
)
201 struct x11_swapchain
*chain
= (struct x11_swapchain
*)anv_chain
;
203 if (pSwapchainImages
== NULL
) {
204 *pCount
= chain
->image_count
;
208 assert(chain
->image_count
<= *pCount
);
209 for (uint32_t i
= 0; i
< chain
->image_count
; i
++)
210 pSwapchainImages
[i
] = anv_image_to_handle(chain
->images
[i
].image
);
212 *pCount
= chain
->image_count
;
218 x11_acquire_next_image(struct anv_swapchain
*anv_chain
,
220 VkSemaphore semaphore
,
221 uint32_t *image_index
)
223 struct x11_swapchain
*chain
= (struct x11_swapchain
*)anv_chain
;
224 struct x11_image
*image
= &chain
->images
[chain
->next_image
];
227 xcb_generic_error_t
*err
;
228 xcb_get_geometry_reply_t
*geom
=
229 xcb_get_geometry_reply(chain
->conn
, image
->geom_cookie
, &err
);
232 return vk_error(VK_ERROR_OUT_OF_DATE_KHR
);
235 if (geom
->width
!= chain
->extent
.width
||
236 geom
->height
!= chain
->extent
.height
) {
238 return vk_error(VK_ERROR_OUT_OF_DATE_KHR
);
245 *image_index
= chain
->next_image
;
246 chain
->next_image
= (chain
->next_image
+ 1) % chain
->image_count
;
251 x11_queue_present(struct anv_swapchain
*anv_chain
,
252 struct anv_queue
*queue
,
253 uint32_t image_index
)
255 struct x11_swapchain
*chain
= (struct x11_swapchain
*)anv_chain
;
256 struct x11_image
*image
= &chain
->images
[image_index
];
258 assert(image_index
< chain
->image_count
);
260 xcb_void_cookie_t cookie
;
262 cookie
= xcb_copy_area(chain
->conn
,
269 chain
->extent
.height
);
270 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
272 image
->geom_cookie
= xcb_get_geometry(chain
->conn
, chain
->window
);
275 xcb_flush(chain
->conn
);
281 x11_swapchain_destroy(struct anv_swapchain
*anv_chain
,
282 const VkAllocationCallbacks
*pAllocator
)
284 struct x11_swapchain
*chain
= (struct x11_swapchain
*)anv_chain
;
285 xcb_void_cookie_t cookie
;
287 for (uint32_t i
= 0; i
< chain
->image_count
; i
++) {
288 struct x11_image
*image
= &chain
->images
[i
];
291 xcb_discard_reply(chain
->conn
, image
->geom_cookie
.sequence
);
293 cookie
= xcb_free_pixmap(chain
->conn
, image
->pixmap
);
294 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
296 /* TODO: Delete images and free memory */
299 anv_free(NULL
/* XXX: pAllocator */, chain
);
305 x11_surface_create_swapchain(struct anv_wsi_surface
*wsi_surface
,
306 struct anv_device
*device
,
307 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
308 const VkAllocationCallbacks
* pAllocator
,
309 struct anv_swapchain
**swapchain_out
)
311 struct x11_surface
*surface
= (struct x11_surface
*)wsi_surface
;
312 struct x11_swapchain
*chain
;
313 xcb_void_cookie_t cookie
;
316 int num_images
= pCreateInfo
->minImageCount
;
318 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
);
320 size_t size
= sizeof(*chain
) + num_images
* sizeof(chain
->images
[0]);
321 chain
= anv_alloc2(&device
->alloc
, pAllocator
, size
, 8,
322 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
324 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
326 chain
->base
.device
= device
;
327 chain
->base
.destroy
= x11_swapchain_destroy
;
328 chain
->base
.get_images
= x11_get_images
;
329 chain
->base
.acquire_next_image
= x11_acquire_next_image
;
330 chain
->base
.queue_present
= x11_queue_present
;
332 chain
->conn
= surface
->connection
;
333 chain
->window
= surface
->window
;
334 chain
->extent
= pCreateInfo
->imageExtent
;
335 chain
->image_count
= num_images
;
336 chain
->next_image
= 0;
338 for (uint32_t i
= 0; i
< chain
->image_count
; i
++) {
339 VkDeviceMemory memory_h
;
341 struct anv_image
*image
;
342 struct anv_surface
*surface
;
343 struct anv_device_memory
*memory
;
345 anv_image_create(anv_device_to_handle(device
),
346 &(struct anv_image_create_info
) {
347 .force_tiling
= true,
348 .tiling
= ISL_TILING_X
,
351 &(VkImageCreateInfo
) {
352 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
353 .imageType
= VK_IMAGE_TYPE_2D
,
354 .format
= pCreateInfo
->imageFormat
,
356 .width
= pCreateInfo
->imageExtent
.width
,
357 .height
= pCreateInfo
->imageExtent
.height
,
363 /* FIXME: Need a way to use X tiling to allow scanout */
364 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
365 .usage
= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
,
371 image
= anv_image_from_handle(image_h
);
372 assert(anv_format_is_color(image
->format
));
374 surface
= &image
->color_surface
;
376 anv_AllocateMemory(anv_device_to_handle(device
),
377 &(VkMemoryAllocateInfo
) {
378 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
379 .allocationSize
= image
->size
,
380 .memoryTypeIndex
= 0,
382 NULL
/* XXX: pAllocator */,
385 memory
= anv_device_memory_from_handle(memory_h
);
387 anv_BindImageMemory(VK_NULL_HANDLE
, anv_image_to_handle(image
),
390 int ret
= anv_gem_set_tiling(device
, memory
->bo
.gem_handle
,
391 surface
->stride
, I915_TILING_X
);
393 /* FINISHME: Choose a better error. */
394 result
= vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY
,
395 "set_tiling failed: %m");
399 int fd
= anv_gem_handle_to_fd(device
, memory
->bo
.gem_handle
);
401 /* FINISHME: Choose a better error. */
402 result
= vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY
,
403 "handle_to_fd failed: %m");
409 xcb_pixmap_t pixmap
= xcb_generate_id(chain
->conn
);
412 xcb_dri3_pixmap_from_buffer_checked(chain
->conn
,
416 pCreateInfo
->imageExtent
.width
,
417 pCreateInfo
->imageExtent
.height
,
421 chain
->images
[i
].image
= image
;
422 chain
->images
[i
].memory
= memory
;
423 chain
->images
[i
].pixmap
= pixmap
;
424 chain
->images
[i
].busy
= false;
426 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
429 chain
->gc
= xcb_generate_id(chain
->conn
);
431 /* FINISHME: Choose a better error. */
432 result
= vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
436 cookie
= xcb_create_gc(chain
->conn
,
439 XCB_GC_GRAPHICS_EXPOSURES
,
440 (uint32_t []) { 0 });
441 xcb_discard_reply(chain
->conn
, cookie
.sequence
);
443 *swapchain_out
= &chain
->base
;
452 anv_x11_init_wsi(struct anv_instance
*instance
)
458 anv_x11_finish_wsi(struct anv_instance
*instance
)