2 * Xephyr - A kdrive X server thats runs in a host X window.
3 * Authored by Matthew Allum <mallum@openedhand.com>
5 * Copyright © 2007 OpenedHand Ltd
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.
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.
25 * a lots of the content of this file has been adapted from the mesa source
28 * Dodji Seketeli <dodji@openedhand.com>
31 #include <kdrive-config.h>
34 #include <X11/Xdefs.h>
36 #include <GL/glxproto.h>
38 #include "ephyrhostglx.h"
39 #define _HAVE_XALLOC_DECLS
43 static int glx_major
, glx_minor
;
45 enum VisualConfRequestType
{
47 EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX
,
48 EPHYR_GET_VISUAL_CONFIGS
51 static Bool ephyrHostGLXGetVisualConfigsInternal
52 (enum VisualConfRequestType a_type
,
53 xcb_glx_get_visual_configs_reply_t
*reply
,
55 int32_t *a_num_visuals
,
57 int32_t *a_props_buf_size
,
58 int32_t **a_props_buf
);
61 ephyrHostGLXQueryVersion(int *a_major
, int *a_minor
)
64 xcb_connection_t
*conn
= hostx_get_xcbconn();
65 xcb_glx_query_version_cookie_t cookie
;
66 xcb_glx_query_version_reply_t
*reply
;
68 EPHYR_RETURN_VAL_IF_FAIL(a_major
&& a_minor
, FALSE
);
77 /* Send the glXQueryVersion request */
78 cookie
= xcb_glx_query_version(conn
, 2, 1);
79 reply
= xcb_glx_query_version_reply(conn
, cookie
, NULL
);
82 *a_major
= reply
->major_version
;
83 *a_minor
= reply
->minor_version
;
86 EPHYR_LOG("major:%d, minor:%d\n", *a_major
, *a_minor
);
95 ephyrHostGLXGetString(int a_context_tag
,
100 xcb_connection_t
*conn
= hostx_get_xcbconn();
101 xcb_glx_get_string_cookie_t cookie
;
102 xcb_glx_get_string_reply_t
*reply
;
104 EPHYR_RETURN_VAL_IF_FAIL(conn
&& a_string
, FALSE
);
106 EPHYR_LOG("enter\n");
107 cookie
= xcb_glx_get_string(conn
, a_context_tag
, a_string_name
);
108 reply
= xcb_glx_get_string_reply(conn
, cookie
, NULL
);
111 *a_string
= malloc(reply
->n
+ 1);
112 memcpy(*a_string
, xcb_glx_get_string_string(reply
), reply
->n
);
113 (*a_string
)[reply
->n
] = '\0';
117 EPHYR_LOG("leave\n");
121 Bool
ephyrHostGLXQueryServerString(int a_screen_number
,
126 xcb_connection_t
*conn
= hostx_get_xcbconn();
127 int default_screen
= hostx_get_screen();
128 xcb_glx_query_server_string_cookie_t cookie
;
129 xcb_glx_query_server_string_reply_t
*reply
;
131 EPHYR_RETURN_VAL_IF_FAIL(conn
&& a_string
, FALSE
);
133 EPHYR_LOG("enter\n");
134 cookie
= xcb_glx_query_server_string(conn
, default_screen
, a_string_name
);
135 reply
= xcb_glx_query_server_string_reply(conn
, cookie
, NULL
);
138 *a_string
= malloc(reply
->str_len
+ 1);
139 memcpy(*a_string
, xcb_glx_query_server_string_string(reply
), reply
->str_len
);
140 (*a_string
)[reply
->str_len
] = '\0';
144 EPHYR_LOG("leave\n");
149 ephyrHostGLXGetVisualConfigsInternal(enum VisualConfRequestType a_type
,
150 xcb_glx_get_visual_configs_reply_t
*reply
,
152 int32_t * a_num_visuals
,
153 int32_t * a_num_props
,
154 int32_t * a_props_buf_size
,
155 int32_t ** a_props_buf
)
158 int num_props
= 0, num_visuals
= 0, props_buf_size
= 0;
159 int props_per_visual_size
= 0;
160 int32_t *props_buf
= NULL
;
162 if (!reply
->num_visuals
) {
163 EPHYR_LOG_ERROR("screen does not support GL rendering\n");
166 num_visuals
= reply
->num_visuals
;
168 num_props
= reply
->num_properties
;
170 if (a_type
!= EPHYR_GET_VISUAL_CONFIGS
) {
173 props_per_visual_size
= num_props
* sizeof(uint32_t);
174 props_buf_size
= props_per_visual_size
* reply
->num_visuals
;
175 props_buf
= malloc(props_buf_size
);
178 memcpy(props_buf
, xcb_glx_get_visual_configs_property_list(reply
),
181 *a_num_visuals
= num_visuals
;
182 *a_num_props
= reply
->num_properties
;
183 *a_props_buf_size
= props_buf_size
;
184 *a_props_buf
= props_buf
;
192 ephyrHostGLXGetVisualConfigs(int32_t a_screen
,
193 int32_t * a_num_visuals
,
194 int32_t * a_num_props
,
195 int32_t * a_props_buf_size
, int32_t ** a_props_buf
)
198 xcb_glx_get_visual_configs_cookie_t cookie
;
199 xcb_glx_get_visual_configs_reply_t
*reply
;
200 xcb_connection_t
*conn
= hostx_get_xcbconn();
201 int screen
= hostx_get_screen();
203 EPHYR_LOG("enter\n");
204 cookie
= xcb_glx_get_visual_configs(conn
, screen
);
205 reply
= xcb_glx_get_visual_configs_reply(conn
, cookie
, NULL
);
208 is_ok
= ephyrHostGLXGetVisualConfigsInternal
209 (EPHYR_GET_VISUAL_CONFIGS
,
219 EPHYR_LOG("leave:%d\n", is_ok
);
224 ephyrHostGLXVendorPrivGetFBConfigsSGIX(int a_screen
,
225 int32_t * a_num_visuals
,
226 int32_t * a_num_props
,
227 int32_t * a_props_buf_size
,
228 int32_t ** a_props_buf
)
231 xcb_connection_t
*conn
= hostx_get_xcbconn();
232 int screen
= hostx_get_screen();
233 xcb_glx_vendor_private_with_reply_cookie_t cookie
;
235 xcb_glx_vendor_private_with_reply_reply_t
*vprep
;
236 xcb_glx_get_visual_configs_reply_t
*rep
;
239 EPHYR_LOG("enter\n");
240 cookie
= xcb_glx_vendor_private_with_reply(conn
,
241 X_GLXvop_GetFBConfigsSGIX
,
242 0, 4, (uint8_t *)&screen
);
243 reply
.vprep
= xcb_glx_vendor_private_with_reply_reply(conn
, cookie
, NULL
);
246 is_ok
= ephyrHostGLXGetVisualConfigsInternal
247 (EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX
,
256 EPHYR_LOG("leave\n");
261 ephyrHostGLXSendClientInfo(int32_t a_major
, int32_t a_minor
,
262 const char *a_extension_list
)
264 xcb_connection_t
*conn
= hostx_get_xcbconn();
267 EPHYR_RETURN_VAL_IF_FAIL(conn
&& a_extension_list
, FALSE
);
269 size
= strlen (a_extension_list
) + 1;
270 xcb_glx_client_info(conn
, a_major
, a_minor
, size
, a_extension_list
);
276 ephyrHostGLXCreateContext(int a_screen
,
279 int a_share_list_ctxt_id
,
284 xcb_connection_t
*conn
= hostx_get_xcbconn();
286 int remote_context_id
= 0;
288 EPHYR_LOG("enter. screen:%d, generic_id:%d, contextid:%d, rendertype:%d, "
289 "direct:%d\n", a_screen
, a_generic_id
, a_context_id
,
290 a_render_type
, a_direct
);
292 if (!hostx_allocate_resource_id_peer(a_context_id
, &remote_context_id
)) {
293 EPHYR_LOG_ERROR("failed to peer the context id %d host X",
299 case X_GLXCreateContext
: {
300 xcb_glx_create_context(conn
,
304 a_share_list_ctxt_id
,
308 case X_GLXCreateNewContext
: {
309 xcb_glx_create_new_context(conn
,
314 a_share_list_ctxt_id
,
319 /* This should never be reached !*/
320 EPHYR_LOG("Internal error! Invalid CreateContext code!\n");
326 EPHYR_LOG("leave\n");
331 ephyrHostDestroyContext(int a_ctxt_id
)
333 xcb_connection_t
*conn
= hostx_get_xcbconn();
335 int remote_ctxt_id
= 0;
337 EPHYR_LOG("enter:%d\n", a_ctxt_id
);
339 if (!hostx_get_resource_id_peer(a_ctxt_id
, &remote_ctxt_id
)) {
340 EPHYR_LOG_ERROR("failed to get remote glx ctxt id\n");
343 EPHYR_LOG("host context id:%d\n", remote_ctxt_id
);
345 xcb_glx_destroy_context(conn
, remote_ctxt_id
);
350 EPHYR_LOG("leave\n");
355 ephyrHostGLXMakeCurrent(int a_drawable
, int a_readable
,
356 int a_glx_ctxt_id
, int a_old_ctxt_tag
, int *a_ctxt_tag
)
358 xcb_connection_t
*conn
= hostx_get_xcbconn();
360 int remote_glx_ctxt_id
= 0;
362 EPHYR_RETURN_VAL_IF_FAIL(a_ctxt_tag
, FALSE
);
364 EPHYR_LOG("enter. drawable:%d, read:%d, context:%d, oldtag:%d\n",
365 a_drawable
, a_readable
, a_glx_ctxt_id
, a_old_ctxt_tag
);
367 if (!hostx_get_resource_id_peer(a_glx_ctxt_id
, &remote_glx_ctxt_id
)) {
368 EPHYR_LOG_ERROR("failed to get remote glx ctxt id\n");
372 /* If both drawables are the same, use the old MakeCurrent request.
373 * Otherwise, if we have GLX 1.3 or higher, use the MakeContextCurrent
374 * request which supports separate read and draw targets. Failing that,
375 * try the SGI MakeCurrentRead extension. Logic cribbed from Mesa. */
376 if (a_drawable
== a_readable
) {
377 xcb_glx_make_current_cookie_t cookie
;
378 xcb_glx_make_current_reply_t
*reply
;
379 cookie
= xcb_glx_make_current(conn
,
383 reply
= xcb_glx_make_current_reply(conn
, cookie
, NULL
);
386 *a_ctxt_tag
= reply
->context_tag
;
389 else if (glx_major
> 1 || glx_minor
>= 3) {
390 xcb_glx_make_context_current_cookie_t cookie
;
391 xcb_glx_make_context_current_reply_t
*reply
;
392 cookie
= xcb_glx_make_context_current(conn
,
397 reply
= xcb_glx_make_context_current_reply(conn
, cookie
, NULL
);
400 *a_ctxt_tag
= reply
->context_tag
;
404 xcb_glx_vendor_private_with_reply_cookie_t cookie
;
405 xcb_glx_vendor_private_with_reply_reply_t
*reply
;
407 a_drawable
, a_readable
, remote_glx_ctxt_id
,
410 EPHYR_LOG("enter\n");
411 cookie
= xcb_glx_vendor_private_with_reply(conn
,
412 X_GLXvop_MakeCurrentReadSGI
,
416 reply
= xcb_glx_vendor_private_with_reply_reply(conn
, cookie
, NULL
);
418 *a_ctxt_tag
= reply
->retval
;
423 EPHYR_LOG("context tag:%d\n", *a_ctxt_tag
);
427 EPHYR_LOG("leave\n");
432 ephyrHostGetIntegerValue(int a_current_context_tag
, int a_int
, int *a_val
)
434 xcb_connection_t
*conn
= hostx_get_xcbconn();
437 xcb_glx_get_integerv_cookie_t cookie
;
438 xcb_glx_get_integerv_reply_t
*reply
;
440 EPHYR_RETURN_VAL_IF_FAIL(a_val
, FALSE
);
442 EPHYR_LOG("enter\n");
443 cookie
= xcb_glx_get_integerv(conn
, a_current_context_tag
, a_int
);
444 reply
= xcb_glx_get_integerv_reply(conn
, cookie
, NULL
);
449 EPHYR_LOG_ERROR("X_GLsop_GetIngerv failed\n");
452 *a_val
= reply
->datum
;
457 EPHYR_LOG("leave\n");
462 ephyrHostIsContextDirect(int a_ctxt_id
, int *a_is_direct
)
465 xcb_connection_t
*conn
= hostx_get_xcbconn();
466 xcb_glx_is_direct_cookie_t cookie
;
467 xcb_glx_is_direct_reply_t
*reply
= NULL
;
468 int remote_glx_ctxt_id
= 0;
470 EPHYR_LOG("enter\n");
471 if (!hostx_get_resource_id_peer (a_ctxt_id
, &remote_glx_ctxt_id
)) {
472 EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n");
476 /* Send the glXIsDirect request */
477 cookie
= xcb_glx_is_direct(conn
, remote_glx_ctxt_id
);
478 reply
= xcb_glx_is_direct_reply(conn
, cookie
, NULL
);
480 EPHYR_LOG_ERROR("fail in reading reply from host\n");
483 *a_is_direct
= reply
->is_direct
;
488 EPHYR_LOG("leave\n");