Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Xephyr - A kdrive X server thats runs in a host X window. | |
3 | * Authored by Matthew Allum <mallum@openedhand.com> | |
4 | * | |
5 | * Copyright © 2007 OpenedHand Ltd | |
6 | * | |
7 | * Permission to use, copy, modify, distribute, and sell this software and its | |
8 | * documentation for any purpose is hereby granted without fee, provided that | |
9 | * the above copyright notice appear in all copies and that both that | |
10 | * copyright notice and this permission notice appear in supporting | |
11 | * documentation, and that the name of OpenedHand Ltd not be used in | |
12 | * advertising or publicity pertaining to distribution of the software without | |
13 | * specific, written prior permission. OpenedHand Ltd makes no | |
14 | * representations about the suitability of this software for any purpose. It | |
15 | * is provided "as is" without express or implied warranty. | |
16 | * | |
17 | * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |
18 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |
19 | * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |
20 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |
21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |
22 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
23 | * PERFORMANCE OF THIS SOFTWARE. | |
24 | * | |
25 | * Authors: | |
26 | * Dodji Seketeli <dodji@openedhand.com> | |
27 | */ | |
28 | #ifdef HAVE_CONFIG_H | |
29 | #include <kdrive-config.h> | |
30 | #endif | |
31 | ||
32 | #include <X11/Xdefs.h> | |
33 | #include <xcb/xf86dri.h> | |
34 | #include "hostx.h" | |
35 | #include "ephyrdri.h" | |
36 | #define _HAVE_XALLOC_DECLS | |
37 | #include "ephyrlog.h" | |
38 | #include "dixstruct.h" | |
39 | #include "pixmapstr.h" | |
40 | ||
41 | #ifndef TRUE | |
42 | #define TRUE 1 | |
43 | #endif /*TRUE*/ | |
44 | #ifndef FALSE | |
45 | #define FALSE 0 | |
46 | #endif /*FALSE*/ | |
47 | Bool | |
48 | ephyrDRIQueryDirectRenderingCapable(int a_screen, Bool *a_is_capable) | |
49 | { | |
50 | xcb_connection_t *conn = hostx_get_xcbconn(); | |
51 | Bool is_ok = FALSE; | |
52 | xcb_xf86dri_query_direct_rendering_capable_cookie_t cookie; | |
53 | xcb_xf86dri_query_direct_rendering_capable_reply_t *reply; | |
54 | ||
55 | EPHYR_RETURN_VAL_IF_FAIL(a_is_capable, FALSE); | |
56 | EPHYR_LOG("enter\n"); | |
57 | cookie = xcb_xf86dri_query_direct_rendering_capable(conn, | |
58 | hostx_get_screen()); | |
59 | reply = xcb_xf86dri_query_direct_rendering_capable_reply(conn, cookie, NULL); | |
60 | if (reply) { | |
61 | is_ok = TRUE; | |
62 | *a_is_capable = reply->is_capable; | |
63 | free(reply); | |
64 | } | |
65 | EPHYR_LOG("leave. is_capable:%d, is_ok=%d\n", *a_is_capable, is_ok); | |
66 | ||
67 | return is_ok; | |
68 | } | |
69 | ||
70 | Bool | |
71 | ephyrDRIOpenConnection(int a_screen, | |
72 | drm_handle_t * a_sarea, char **a_bus_id_string) | |
73 | { | |
74 | xcb_connection_t *conn = hostx_get_xcbconn(); | |
75 | Bool is_ok = FALSE; | |
76 | xcb_xf86dri_open_connection_cookie_t cookie; | |
77 | xcb_xf86dri_open_connection_reply_t *reply; | |
78 | ||
79 | EPHYR_RETURN_VAL_IF_FAIL(a_bus_id_string, FALSE); | |
80 | EPHYR_LOG("enter. screen:%d\n", a_screen); | |
81 | cookie = xcb_xf86dri_open_connection(conn, hostx_get_screen()); | |
82 | reply = xcb_xf86dri_open_connection_reply(conn, cookie, NULL); | |
83 | if (!reply) | |
84 | goto out; | |
85 | *a_sarea = reply->sarea_handle_low; | |
86 | if (sizeof(drm_handle_t) == 8) { | |
87 | int shift = 32; | |
88 | *a_sarea |= ((drm_handle_t) reply->sarea_handle_high) << shift; | |
89 | } | |
90 | *a_bus_id_string = malloc(reply->bus_id_len + 1); | |
91 | if (!*a_bus_id_string) | |
92 | goto out; | |
93 | memcpy(*a_bus_id_string, xcb_xf86dri_open_connection_bus_id(reply), reply->bus_id_len); | |
94 | *a_bus_id_string[reply->bus_id_len] = '\0'; | |
95 | is_ok = TRUE; | |
96 | out: | |
97 | free(reply); | |
98 | EPHYR_LOG("leave. bus_id_string:%s, is_ok:%d\n", *a_bus_id_string, is_ok); | |
99 | return is_ok; | |
100 | } | |
101 | ||
102 | Bool | |
103 | ephyrDRIAuthConnection(int a_screen, drm_magic_t a_magic) | |
104 | { | |
105 | xcb_connection_t *conn = hostx_get_xcbconn(); | |
106 | int screen = hostx_get_screen(); | |
107 | xcb_xf86dri_auth_connection_cookie_t cookie; | |
108 | xcb_xf86dri_auth_connection_reply_t *reply; | |
109 | Bool is_ok = FALSE; | |
110 | ||
111 | EPHYR_LOG("enter\n"); | |
112 | cookie = xcb_xf86dri_auth_connection(conn, screen, a_magic); | |
113 | reply = xcb_xf86dri_auth_connection_reply(conn, cookie, NULL); | |
114 | is_ok = reply->authenticated; | |
115 | free(reply); | |
116 | EPHYR_LOG("leave. is_ok:%d\n", is_ok); | |
117 | return is_ok; | |
118 | } | |
119 | ||
120 | Bool | |
121 | ephyrDRICloseConnection(int a_screen) | |
122 | { | |
123 | xcb_connection_t *conn = hostx_get_xcbconn(); | |
124 | int screen = hostx_get_screen(); | |
125 | ||
126 | EPHYR_LOG("enter\n"); | |
127 | xcb_xf86dri_close_connection(conn, screen); | |
128 | EPHYR_LOG("leave\n"); | |
129 | return TRUE; | |
130 | } | |
131 | ||
132 | Bool | |
133 | ephyrDRIGetClientDriverName(int a_screen, | |
134 | int *a_ddx_driver_major_version, | |
135 | int *a_ddx_driver_minor_version, | |
136 | int *a_ddx_driver_patch_version, | |
137 | char **a_client_driver_name) | |
138 | { | |
139 | xcb_connection_t *conn = hostx_get_xcbconn(); | |
140 | int screen = hostx_get_screen(); | |
141 | xcb_xf86dri_get_client_driver_name_cookie_t cookie; | |
142 | xcb_xf86dri_get_client_driver_name_reply_t *reply; | |
143 | Bool is_ok = FALSE; | |
144 | ||
145 | EPHYR_RETURN_VAL_IF_FAIL(a_ddx_driver_major_version | |
146 | && a_ddx_driver_minor_version | |
147 | && a_ddx_driver_patch_version | |
148 | && a_client_driver_name, FALSE); | |
149 | EPHYR_LOG("enter\n"); | |
150 | cookie = xcb_xf86dri_get_client_driver_name(conn, screen); | |
151 | reply = xcb_xf86dri_get_client_driver_name_reply(conn, cookie, NULL); | |
152 | if (!reply) | |
153 | goto out; | |
154 | *a_ddx_driver_major_version = reply->client_driver_major_version; | |
155 | *a_ddx_driver_minor_version = reply->client_driver_minor_version; | |
156 | *a_ddx_driver_patch_version = reply->client_driver_patch_version; | |
157 | *a_client_driver_name = malloc(reply->client_driver_name_len + 1); | |
158 | if (!*a_client_driver_name) | |
159 | goto out; | |
160 | memcpy(*a_client_driver_name, | |
161 | xcb_xf86dri_get_client_driver_name_client_driver_name(reply), | |
162 | reply->client_driver_name_len); | |
163 | (*a_client_driver_name)[reply->client_driver_name_len] = '\0'; | |
164 | is_ok = TRUE; | |
165 | EPHYR_LOG("major:%d, minor:%d, patch:%d, name:%s\n", | |
166 | *a_ddx_driver_major_version, | |
167 | *a_ddx_driver_minor_version, | |
168 | *a_ddx_driver_patch_version, *a_client_driver_name); | |
169 | out: | |
170 | free(reply); | |
171 | EPHYR_LOG("leave:%d\n", is_ok); | |
172 | return is_ok; | |
173 | } | |
174 | ||
175 | Bool | |
176 | ephyrDRICreateContext(int a_screen, | |
177 | int a_visual_id, | |
178 | CARD32 ctxt_id, drm_context_t * a_hw_ctxt) | |
179 | { | |
180 | xcb_connection_t *conn = hostx_get_xcbconn(); | |
181 | int screen = hostx_get_screen(); | |
182 | Bool is_ok = FALSE; | |
183 | xcb_xf86dri_create_context_cookie_t cookie; | |
184 | xcb_xf86dri_create_context_reply_t *reply; | |
185 | ||
186 | ctxt_id = xcb_generate_id(conn); | |
187 | ||
188 | EPHYR_LOG("enter. screen:%d, visual:%d\n", a_screen, a_visual_id); | |
189 | cookie = xcb_xf86dri_create_context(conn, screen, a_visual_id, ctxt_id); | |
190 | reply = xcb_xf86dri_create_context_reply(conn, cookie, NULL); | |
191 | if (!reply) | |
192 | goto out; | |
193 | *a_hw_ctxt = reply->hw_context; | |
194 | is_ok = TRUE; | |
195 | out: | |
196 | free(reply); | |
197 | EPHYR_LOG("leave:%d\n", is_ok); | |
198 | return is_ok; | |
199 | } | |
200 | ||
201 | Bool | |
202 | ephyrDRIDestroyContext(int a_screen, int a_context_id) | |
203 | { | |
204 | xcb_connection_t *conn = hostx_get_xcbconn (); | |
205 | int screen = hostx_get_screen(); | |
206 | ||
207 | EPHYR_LOG("enter\n"); | |
208 | xcb_xf86dri_destroy_context(conn, screen, a_context_id); | |
209 | EPHYR_LOG("leave\n"); | |
210 | return TRUE; | |
211 | } | |
212 | ||
213 | Bool | |
214 | ephyrDRICreateDrawable(int a_screen, | |
215 | int a_drawable, drm_drawable_t * a_hw_drawable) | |
216 | { | |
217 | Bool is_ok = FALSE; | |
218 | xcb_connection_t *conn = hostx_get_xcbconn(); | |
219 | int screen = hostx_get_screen(); | |
220 | xcb_xf86dri_create_drawable_cookie_t cookie; | |
221 | xcb_xf86dri_create_drawable_reply_t *reply; | |
222 | ||
223 | EPHYR_LOG("enter\n"); | |
224 | cookie = xcb_xf86dri_create_drawable(conn, screen, a_drawable); | |
225 | reply = xcb_xf86dri_create_drawable_reply(conn, cookie, NULL); | |
226 | if (!reply) | |
227 | goto out; | |
228 | *a_hw_drawable = reply->hw_drawable_handle; | |
229 | is_ok = TRUE; | |
230 | out: | |
231 | free(reply); | |
232 | EPHYR_LOG("leave. is_ok:%d\n", is_ok); | |
233 | return is_ok; | |
234 | } | |
235 | ||
236 | Bool | |
237 | ephyrDRIDestroyDrawable(int a_screen, int a_drawable) | |
238 | { | |
239 | EPHYR_LOG("enter\n"); | |
240 | EPHYR_LOG_ERROR("not implemented yet\n"); | |
241 | EPHYR_LOG("leave\n"); | |
242 | return FALSE; | |
243 | } | |
244 | ||
245 | Bool | |
246 | ephyrDRIGetDrawableInfo(int a_screen, | |
247 | int a_drawable, | |
248 | unsigned int *a_index, | |
249 | unsigned int *a_stamp, | |
250 | int *a_x, | |
251 | int *a_y, | |
252 | int *a_w, | |
253 | int *a_h, | |
254 | int *a_num_clip_rects, | |
255 | drm_clip_rect_t ** a_clip_rects, | |
256 | int *a_back_x, | |
257 | int *a_back_y, | |
258 | int *a_num_back_clip_rects, | |
259 | drm_clip_rect_t ** a_back_clip_rects) | |
260 | { | |
261 | Bool is_ok = FALSE; | |
262 | xcb_connection_t *conn = hostx_get_xcbconn(); | |
263 | int screen = hostx_get_screen(); | |
264 | xcb_xf86dri_get_drawable_info_cookie_t cookie; | |
265 | xcb_xf86dri_get_drawable_info_reply_t *reply = NULL; | |
266 | EphyrHostWindowAttributes attrs; | |
267 | ||
268 | EPHYR_RETURN_VAL_IF_FAIL(a_x && a_y && a_w && a_h | |
269 | && a_num_clip_rects, FALSE); | |
270 | ||
271 | EPHYR_LOG("enter\n"); | |
272 | memset(&attrs, 0, sizeof(attrs)); | |
273 | if (!hostx_get_window_attributes(a_drawable, &attrs)) { | |
274 | EPHYR_LOG_ERROR("failed to query host window attributes\n"); | |
275 | goto out; | |
276 | } | |
277 | cookie = xcb_xf86dri_get_drawable_info(conn, screen, a_drawable); | |
278 | reply = xcb_xf86dri_get_drawable_info_reply(conn, cookie, NULL); | |
279 | if (!reply) { | |
280 | EPHYR_LOG_ERROR ("XF86DRIGetDrawableInfo ()\n"); | |
281 | goto out; | |
282 | } | |
283 | *a_index = reply->drawable_table_index; | |
284 | *a_stamp = reply->drawable_table_stamp; | |
285 | *a_x = reply->drawable_origin_X; | |
286 | *a_y = reply->drawable_origin_Y; | |
287 | *a_w = reply->drawable_size_W; | |
288 | *a_h = reply->drawable_size_H; | |
289 | *a_num_clip_rects = reply->num_clip_rects; | |
290 | *a_clip_rects = calloc(*a_num_clip_rects, sizeof(drm_clip_rect_t)); | |
291 | memcpy(*a_clip_rects, xcb_xf86dri_get_drawable_info_clip_rects(reply), | |
292 | *a_num_clip_rects * sizeof(drm_clip_rect_t)); | |
293 | EPHYR_LOG("host x,y,w,h: (%d,%d,%d,%d)\n", *a_x, *a_y, *a_w, *a_h); | |
294 | if (*a_num_clip_rects) { | |
295 | free(*a_back_clip_rects); | |
296 | *a_back_clip_rects = calloc(*a_num_clip_rects, sizeof(drm_clip_rect_t)); | |
297 | memmove(*a_back_clip_rects, | |
298 | *a_clip_rects, *a_num_clip_rects * sizeof(drm_clip_rect_t)); | |
299 | *a_num_back_clip_rects = *a_num_clip_rects; | |
300 | } | |
301 | EPHYR_LOG("num back clip rects:%d, num clip rects:%d\n", | |
302 | *a_num_clip_rects, *a_num_back_clip_rects); | |
303 | *a_back_x = *a_x; | |
304 | *a_back_y = *a_y; | |
305 | *a_w = attrs.width; | |
306 | *a_h = attrs.height; | |
307 | ||
308 | is_ok = TRUE; | |
309 | out: | |
310 | EPHYR_LOG("leave. index:%d, stamp:%d, x,y:(%d,%d), w,y:(%d,%d)\n", | |
311 | *a_index, *a_stamp, *a_x, *a_y, *a_w, *a_h); | |
312 | free(reply); | |
313 | return is_ok; | |
314 | } | |
315 | ||
316 | Bool | |
317 | ephyrDRIGetDeviceInfo(int a_screen, | |
318 | drm_handle_t * a_frame_buffer, | |
319 | int *a_fb_origin, | |
320 | int *a_fb_size, | |
321 | int *a_fb_stride, | |
322 | int *a_dev_private_size, void **a_dev_private) | |
323 | { | |
324 | Bool is_ok = FALSE; | |
325 | xcb_connection_t *conn = hostx_get_xcbconn (); | |
326 | int screen = hostx_get_screen(); | |
327 | xcb_xf86dri_get_device_info_cookie_t cookie; | |
328 | xcb_xf86dri_get_device_info_reply_t *reply; | |
329 | ||
330 | EPHYR_RETURN_VAL_IF_FAIL(conn, FALSE); | |
331 | EPHYR_LOG("enter\n"); | |
332 | cookie = xcb_xf86dri_get_device_info(conn, screen); | |
333 | reply = xcb_xf86dri_get_device_info_reply(conn, cookie, NULL); | |
334 | if (!reply) | |
335 | goto out; | |
336 | *a_frame_buffer = reply->framebuffer_handle_low; | |
337 | if (sizeof(drm_handle_t) == 8) { | |
338 | int shift = 32; | |
339 | *a_frame_buffer |= ((drm_handle_t)reply->framebuffer_handle_high) << shift; | |
340 | } | |
341 | *a_fb_origin = reply->framebuffer_origin_offset; | |
342 | *a_fb_size = reply->framebuffer_size; | |
343 | *a_fb_stride = reply->framebuffer_stride; | |
344 | *a_dev_private_size = reply->device_private_size; | |
345 | *a_dev_private = calloc(reply->device_private_size, 1); | |
346 | if (!*a_dev_private) | |
347 | goto out; | |
348 | memcpy(*a_dev_private, | |
349 | xcb_xf86dri_get_device_info_device_private(reply), | |
350 | reply->device_private_size); | |
351 | is_ok = TRUE; | |
352 | out: | |
353 | free(reply); | |
354 | EPHYR_LOG("leave:%d\n", is_ok); | |
355 | return is_ok; | |
356 | } |