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 <xcb/glx.h> | |
33 | #include "extnsionst.h" | |
34 | #include "ephyrglxext.h" | |
35 | #include "ephyrhostglx.h" | |
36 | #define _HAVE_XALLOC_DECLS | |
37 | #include "ephyrlog.h" | |
38 | #include <GL/glxproto.h> | |
39 | #include "glx/glxserver.h" | |
40 | #include "glx/indirect_table.h" | |
41 | #include "glx/indirect_util.h" | |
42 | #include "glx/unpack.h" | |
43 | #include "hostx.h" | |
44 | ||
45 | #ifndef TRUE | |
46 | #define TRUE 1 | |
47 | #endif | |
48 | ||
49 | #ifndef FALSE | |
50 | #define FALSE 0 | |
51 | #endif | |
52 | ||
53 | int ephyrGLXQueryVersion(__GLXclientState * cl, GLbyte * pc); | |
54 | int ephyrGLXQueryVersionSwap(__GLXclientState * cl, GLbyte * pc); | |
55 | int ephyrGLXGetVisualConfigs(__GLXclientState * cl, GLbyte * pc); | |
56 | int ephyrGLXGetVisualConfigsSwap(__GLXclientState * cl, GLbyte * pc); | |
57 | int ephyrGLXClientInfo(__GLXclientState * cl, GLbyte * pc); | |
58 | int ephyrGLXClientInfoSwap(__GLXclientState * cl, GLbyte * pc); | |
59 | int ephyrGLXQueryServerString(__GLXclientState * a_cl, GLbyte * a_pc); | |
60 | int ephyrGLXQueryServerStringSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
61 | int ephyrGLXGetFBConfigsSGIX(__GLXclientState * a_cl, GLbyte * a_pc); | |
62 | int ephyrGLXGetFBConfigsSGIXSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
63 | int ephyrGLXCreateContext(__GLXclientState * a_cl, GLbyte * a_pc); | |
64 | int ephyrGLXCreateContextSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
65 | int ephyrGLXCreateNewContext(__GLXclientState * a_cl, GLbyte * a_pc); | |
66 | int ephyrGLXCreateNewContextSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
67 | int ephyrGLXDestroyContext(__GLXclientState * a_cl, GLbyte * a_pc); | |
68 | int ephyrGLXDestroyContextSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
69 | int ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc); | |
70 | int ephyrGLXMakeCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
71 | int ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc); | |
72 | int ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
73 | int ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc); | |
74 | int ephyrGLXMakeContextCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
75 | int ephyrGLXGetString(__GLXclientState * a_cl, GLbyte * a_pc); | |
76 | int ephyrGLXGetStringSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
77 | int ephyrGLXGetIntegerv(__GLXclientState * a_cl, GLbyte * a_pc); | |
78 | int ephyrGLXGetIntegervSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
79 | int ephyrGLXIsDirect(__GLXclientState * a_cl, GLbyte * a_pc); | |
80 | int ephyrGLXIsDirectSwap(__GLXclientState * a_cl, GLbyte * a_pc); | |
81 | ||
82 | Bool | |
83 | ephyrHijackGLXExtension(void) | |
84 | { | |
85 | const void *(*dispatch_functions)[2]; | |
86 | ||
87 | if (!host_has_extension(&xcb_glx_id)) { | |
88 | EPHYR_LOG("host X does not have GLX\n"); | |
89 | return FALSE; | |
90 | } | |
91 | EPHYR_LOG("host X does have GLX\n"); | |
92 | ||
93 | if (!Single_dispatch_info.dispatch_functions) { | |
94 | EPHYR_LOG_ERROR("could not get dispatch functions table\n"); | |
95 | return FALSE; | |
96 | } | |
97 | /* | |
98 | * hijack some single entry point dispatch functions | |
99 | */ | |
100 | dispatch_functions = Single_dispatch_info.dispatch_functions; | |
101 | EPHYR_RETURN_VAL_IF_FAIL(dispatch_functions, FALSE); | |
102 | ||
103 | dispatch_functions[X_GLXQueryVersion][0] = ephyrGLXQueryVersion; | |
104 | dispatch_functions[X_GLXQueryVersion][1] = ephyrGLXQueryVersionSwap; | |
105 | ||
106 | dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs; | |
107 | dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap; | |
108 | dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo; | |
109 | dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap; | |
110 | ||
111 | dispatch_functions[X_GLXQueryServerString][0] = ephyrGLXQueryServerString; | |
112 | dispatch_functions[X_GLXQueryServerString][1] = | |
113 | ephyrGLXQueryServerStringSwap; | |
114 | ||
115 | dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext; | |
116 | dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap; | |
117 | ||
118 | dispatch_functions[X_GLXCreateNewContext][0] = ephyrGLXCreateNewContext; | |
119 | dispatch_functions[X_GLXCreateNewContext][1] = ephyrGLXCreateNewContextSwap; | |
120 | ||
121 | dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext; | |
122 | dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap; | |
123 | ||
124 | dispatch_functions[X_GLXMakeCurrent][0] = ephyrGLXMakeCurrent; | |
125 | dispatch_functions[X_GLXMakeCurrent][1] = ephyrGLXMakeCurrentSwap; | |
126 | ||
127 | dispatch_functions[X_GLXIsDirect][0] = ephyrGLXIsDirect; | |
128 | dispatch_functions[X_GLXIsDirect][1] = ephyrGLXIsDirectSwap; | |
129 | ||
130 | dispatch_functions[73][0] = ephyrGLXGetString; | |
131 | dispatch_functions[73][1] = ephyrGLXGetStringSwap; | |
132 | ||
133 | dispatch_functions[61][0] = ephyrGLXGetIntegerv; | |
134 | dispatch_functions[61][1] = ephyrGLXGetIntegervSwap; | |
135 | ||
136 | dispatch_functions[X_GLXMakeContextCurrent][0] = | |
137 | ephyrGLXMakeContextCurrent; | |
138 | dispatch_functions[X_GLXMakeContextCurrent][1] = | |
139 | ephyrGLXMakeContextCurrentSwap; | |
140 | ||
141 | /* | |
142 | * hijack some vendor priv entry point dispatch functions | |
143 | */ | |
144 | dispatch_functions = VendorPriv_dispatch_info.dispatch_functions; | |
145 | dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX; | |
146 | dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap; | |
147 | ||
148 | dispatch_functions[89][0] = ephyrGLXMakeCurrentReadSGI; | |
149 | dispatch_functions[89][1] = ephyrGLXMakeCurrentReadSGISwap; | |
150 | ||
151 | EPHYR_LOG("hijacked glx entry points to forward requests to host X\n"); | |
152 | ||
153 | ||
154 | return TRUE; | |
155 | } | |
156 | ||
157 | /********************* | |
158 | * implementation of | |
159 | * hijacked GLX entry | |
160 | * points | |
161 | ********************/ | |
162 | ||
163 | int | |
164 | ephyrGLXQueryVersion(__GLXclientState * a_cl, GLbyte * a_pc) | |
165 | { | |
166 | ClientPtr client = a_cl->client; | |
167 | xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; | |
168 | xGLXQueryVersionReply reply; | |
169 | int major, minor; | |
170 | int res = BadImplementation; | |
171 | ||
172 | EPHYR_LOG("enter\n"); | |
173 | ||
174 | major = req->majorVersion; | |
175 | minor = req->minorVersion; | |
176 | ||
177 | if (!ephyrHostGLXQueryVersion(&major, &minor)) { | |
178 | EPHYR_LOG_ERROR("ephyrHostGLXQueryVersion() failed\n"); | |
179 | goto out; | |
180 | } | |
181 | EPHYR_LOG("major:%d, minor:%d\n", major, minor); | |
182 | reply = (xGLXQueryVersionReply) { | |
183 | .type = X_Reply, | |
184 | .sequenceNumber = client->sequence, | |
185 | .length = 0, | |
186 | .majorVersion = major, | |
187 | .minorVersion = minor | |
188 | }; | |
189 | ||
190 | if (client->swapped) { | |
191 | __glXSwapQueryVersionReply(client, &reply); | |
192 | } | |
193 | else { | |
194 | WriteToClient(client, sz_xGLXQueryVersionReply, &reply); | |
195 | } | |
196 | ||
197 | res = Success; | |
198 | out: | |
199 | EPHYR_LOG("leave\n"); | |
200 | return res; | |
201 | } | |
202 | ||
203 | int | |
204 | ephyrGLXQueryVersionSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
205 | { | |
206 | xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; | |
207 | ||
208 | __GLX_DECLARE_SWAP_VARIABLES; | |
209 | ||
210 | __GLX_SWAP_SHORT(&req->length); | |
211 | __GLX_SWAP_INT(&req->majorVersion); | |
212 | __GLX_SWAP_INT(&req->minorVersion); | |
213 | return ephyrGLXQueryVersion(a_cl, a_pc); | |
214 | } | |
215 | ||
216 | static int | |
217 | ephyrGLXGetVisualConfigsReal(__GLXclientState * a_cl, | |
218 | GLbyte * a_pc, Bool a_do_swap) | |
219 | { | |
220 | xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) a_pc; | |
221 | ClientPtr client = a_cl->client; | |
222 | xGLXGetVisualConfigsReply reply; | |
223 | int32_t *props_buf = NULL, num_visuals = 0, | |
224 | num_props = 0, res = BadImplementation, i = 0, | |
225 | props_per_visual_size = 0, props_buf_size = 0; | |
226 | __GLX_DECLARE_SWAP_VARIABLES; | |
227 | __GLX_DECLARE_SWAP_ARRAY_VARIABLES; | |
228 | ||
229 | EPHYR_LOG("enter\n"); | |
230 | ||
231 | if (!ephyrHostGLXGetVisualConfigs(req->screen, | |
232 | &num_visuals, | |
233 | &num_props, | |
234 | &props_buf_size, &props_buf)) { | |
235 | EPHYR_LOG_ERROR("ephyrHostGLXGetVisualConfigs() failed\n"); | |
236 | goto out; | |
237 | } | |
238 | EPHYR_LOG("num_visuals:%d, num_props:%d\n", num_visuals, num_props); | |
239 | ||
240 | reply = (xGLXGetVisualConfigsReply) { | |
241 | .type = X_Reply, | |
242 | .sequenceNumber = client->sequence, | |
243 | .length = (num_visuals * __GLX_SIZE_CARD32 * num_props) >> 2, | |
244 | .numVisuals = num_visuals, | |
245 | .numProps = num_props | |
246 | }; | |
247 | ||
248 | if (a_do_swap) { | |
249 | __GLX_SWAP_SHORT(&reply.sequenceNumber); | |
250 | __GLX_SWAP_INT(&reply.length); | |
251 | __GLX_SWAP_INT(&reply.numVisuals); | |
252 | __GLX_SWAP_INT(&reply.numProps); | |
253 | __GLX_SWAP_INT_ARRAY(props_buf, num_props); | |
254 | } | |
255 | WriteToClient(client, sz_xGLXGetVisualConfigsReply, &reply); | |
256 | props_per_visual_size = props_buf_size / num_visuals; | |
257 | for (i = 0; i < num_visuals; i++) { | |
258 | WriteToClient(client, | |
259 | props_per_visual_size, | |
260 | (char *) props_buf + i * props_per_visual_size); | |
261 | } | |
262 | res = Success; | |
263 | ||
264 | out: | |
265 | EPHYR_LOG("leave\n"); | |
266 | free(props_buf); | |
267 | props_buf = NULL; | |
268 | ||
269 | return res; | |
270 | } | |
271 | ||
272 | static int | |
273 | ephyrGLXGetFBConfigsSGIXReal(__GLXclientState * a_cl, | |
274 | GLbyte * a_pc, Bool a_do_swap) | |
275 | { | |
276 | xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) a_pc; | |
277 | ClientPtr client = a_cl->client; | |
278 | xGLXGetVisualConfigsReply reply; | |
279 | int32_t *props_buf = NULL, num_visuals = 0, | |
280 | num_props = 0, res = BadImplementation, i = 0, | |
281 | props_per_visual_size = 0, props_buf_size = 0; | |
282 | __GLX_DECLARE_SWAP_VARIABLES; | |
283 | __GLX_DECLARE_SWAP_ARRAY_VARIABLES; | |
284 | ||
285 | EPHYR_LOG("enter\n"); | |
286 | ||
287 | if (!ephyrHostGLXVendorPrivGetFBConfigsSGIX(req->screen, | |
288 | &num_visuals, | |
289 | &num_props, | |
290 | &props_buf_size, &props_buf)) { | |
291 | EPHYR_LOG_ERROR("ephyrHostGLXGetVisualConfigs() failed\n"); | |
292 | goto out; | |
293 | } | |
294 | EPHYR_LOG("num_visuals:%d, num_props:%d\n", num_visuals, num_props); | |
295 | ||
296 | reply = (xGLXGetVisualConfigsReply) { | |
297 | .type = X_Reply, | |
298 | .sequenceNumber = client->sequence, | |
299 | .length = props_buf_size >> 2, | |
300 | .numVisuals = num_visuals, | |
301 | .numProps = num_props | |
302 | }; | |
303 | ||
304 | if (a_do_swap) { | |
305 | __GLX_SWAP_SHORT(&reply.sequenceNumber); | |
306 | __GLX_SWAP_INT(&reply.length); | |
307 | __GLX_SWAP_INT(&reply.numVisuals); | |
308 | __GLX_SWAP_INT(&reply.numProps); | |
309 | __GLX_SWAP_INT_ARRAY(props_buf, num_props); | |
310 | } | |
311 | WriteToClient(client, sz_xGLXGetVisualConfigsReply, &reply); | |
312 | props_per_visual_size = props_buf_size / num_visuals; | |
313 | for (i = 0; i < num_visuals; i++) { | |
314 | WriteToClient(client, | |
315 | props_per_visual_size, | |
316 | &((char *) props_buf)[i * props_per_visual_size]); | |
317 | } | |
318 | res = Success; | |
319 | ||
320 | out: | |
321 | EPHYR_LOG("leave\n"); | |
322 | free(props_buf); | |
323 | props_buf = NULL; | |
324 | ||
325 | return res; | |
326 | } | |
327 | ||
328 | int | |
329 | ephyrGLXGetVisualConfigs(__GLXclientState * a_cl, GLbyte * a_pc) | |
330 | { | |
331 | return ephyrGLXGetVisualConfigsReal(a_cl, a_pc, FALSE); | |
332 | } | |
333 | ||
334 | int | |
335 | ephyrGLXGetVisualConfigsSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
336 | { | |
337 | return ephyrGLXGetVisualConfigsReal(a_cl, a_pc, TRUE); | |
338 | } | |
339 | ||
340 | int | |
341 | ephyrGLXClientInfo(__GLXclientState * a_cl, GLbyte * a_pc) | |
342 | { | |
343 | int res = BadImplementation; | |
344 | xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc; | |
345 | ||
346 | EPHYR_LOG("enter\n"); | |
347 | if (!ephyrHostGLXSendClientInfo(req->major, req->minor, (char *) req + 1)) { | |
348 | EPHYR_LOG_ERROR("failed to send client info to host\n"); | |
349 | goto out; | |
350 | } | |
351 | res = Success; | |
352 | ||
353 | out: | |
354 | EPHYR_LOG("leave\n"); | |
355 | return res; | |
356 | } | |
357 | ||
358 | int | |
359 | ephyrGLXClientInfoSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
360 | { | |
361 | xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc; | |
362 | ||
363 | __GLX_DECLARE_SWAP_VARIABLES; | |
364 | ||
365 | __GLX_SWAP_SHORT(&req->length); | |
366 | __GLX_SWAP_INT(&req->major); | |
367 | __GLX_SWAP_INT(&req->minor); | |
368 | __GLX_SWAP_INT(&req->numbytes); | |
369 | ||
370 | return ephyrGLXClientInfo(a_cl, a_pc); | |
371 | } | |
372 | ||
373 | int | |
374 | ephyrGLXQueryServerString(__GLXclientState * a_cl, GLbyte * a_pc) | |
375 | { | |
376 | int res = BadImplementation; | |
377 | ClientPtr client = a_cl->client; | |
378 | xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) a_pc; | |
379 | xGLXQueryServerStringReply reply; | |
380 | char *server_string = NULL; | |
381 | int length = 0; | |
382 | ||
383 | EPHYR_LOG("enter\n"); | |
384 | if (!ephyrHostGLXQueryServerString(req->screen, | |
385 | req->name, | |
386 | &server_string)) { | |
387 | EPHYR_LOG_ERROR("failed to query string from host\n"); | |
388 | goto out; | |
389 | } | |
390 | EPHYR_LOG("string: %s\n", server_string); | |
391 | length = strlen(server_string) + 1; | |
392 | reply = (xGLXQueryServerStringReply) { | |
393 | .type = X_Reply, | |
394 | .sequenceNumber = client->sequence, | |
395 | .length = __GLX_PAD(length) >> 2, | |
396 | .n = length | |
397 | }; | |
398 | ||
399 | WriteToClient(client, sz_xGLXQueryServerStringReply, &reply); | |
400 | WriteToClient(client, (int) (reply.length << 2), server_string); | |
401 | ||
402 | res = Success; | |
403 | ||
404 | out: | |
405 | EPHYR_LOG("leave\n"); | |
406 | free(server_string); | |
407 | server_string = NULL; | |
408 | ||
409 | return res; | |
410 | } | |
411 | ||
412 | int | |
413 | ephyrGLXQueryServerStringSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
414 | { | |
415 | EPHYR_LOG_ERROR("not yet implemented\n"); | |
416 | return BadImplementation; | |
417 | } | |
418 | ||
419 | int | |
420 | ephyrGLXGetFBConfigsSGIX(__GLXclientState * a_cl, GLbyte * a_pc) | |
421 | { | |
422 | return ephyrGLXGetFBConfigsSGIXReal(a_cl, a_pc, FALSE); | |
423 | } | |
424 | ||
425 | int | |
426 | ephyrGLXGetFBConfigsSGIXSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
427 | { | |
428 | return ephyrGLXGetFBConfigsSGIXReal(a_cl, a_pc, TRUE); | |
429 | } | |
430 | ||
431 | static int | |
432 | ephyrGLXCreateContextReal(xGLXCreateContextReq * a_req, Bool a_do_swap) | |
433 | { | |
434 | int res = BadImplementation; | |
435 | EphyrHostWindowAttributes host_w_attrs; | |
436 | ||
437 | __GLX_DECLARE_SWAP_VARIABLES; | |
438 | ||
439 | EPHYR_RETURN_VAL_IF_FAIL(a_req, BadValue); | |
440 | EPHYR_LOG("enter\n"); | |
441 | ||
442 | if (a_do_swap) { | |
443 | __GLX_SWAP_SHORT(&a_req->length); | |
444 | __GLX_SWAP_INT(&a_req->context); | |
445 | __GLX_SWAP_INT(&a_req->visual); | |
446 | __GLX_SWAP_INT(&a_req->screen); | |
447 | __GLX_SWAP_INT(&a_req->shareList); | |
448 | } | |
449 | ||
450 | EPHYR_LOG("context creation requested. localid:%d, " | |
451 | "screen:%d, visual:%d, direct:%d\n", | |
452 | (int) a_req->context, (int) a_req->screen, | |
453 | (int) a_req->visual, (int) a_req->isDirect); | |
454 | ||
455 | memset(&host_w_attrs, 0, sizeof(host_w_attrs)); | |
456 | if (!hostx_get_window_attributes(hostx_get_window(a_req->screen), | |
457 | &host_w_attrs)) { | |
458 | EPHYR_LOG_ERROR("failed to get host window attrs\n"); | |
459 | goto out; | |
460 | } | |
461 | ||
462 | EPHYR_LOG("host window visual id: %d\n", host_w_attrs.visualid); | |
463 | ||
464 | if (!ephyrHostGLXCreateContext(a_req->screen, | |
465 | host_w_attrs.visualid, | |
466 | a_req->context, | |
467 | a_req->shareList, 0, | |
468 | a_req->isDirect, X_GLXCreateContext)) { | |
469 | EPHYR_LOG_ERROR("ephyrHostGLXCreateContext() failed\n"); | |
470 | goto out; | |
471 | } | |
472 | res = Success; | |
473 | out: | |
474 | EPHYR_LOG("leave\n"); | |
475 | return res; | |
476 | } | |
477 | ||
478 | static int | |
479 | ephyrGLXCreateNewContextReal(xGLXCreateNewContextReq * a_req, Bool a_do_swap) | |
480 | { | |
481 | int res = BadImplementation; | |
482 | ||
483 | __GLX_DECLARE_SWAP_VARIABLES; | |
484 | ||
485 | EPHYR_RETURN_VAL_IF_FAIL(a_req, BadValue); | |
486 | EPHYR_LOG("enter\n"); | |
487 | ||
488 | if (a_do_swap) { | |
489 | __GLX_SWAP_SHORT(&a_req->length); | |
490 | __GLX_SWAP_INT(&a_req->context); | |
491 | __GLX_SWAP_INT(&a_req->fbconfig); | |
492 | __GLX_SWAP_INT(&a_req->screen); | |
493 | __GLX_SWAP_INT(&a_req->renderType); | |
494 | __GLX_SWAP_INT(&a_req->shareList); | |
495 | } | |
496 | ||
497 | EPHYR_LOG("context creation requested. localid:%d, " | |
498 | "screen:%d, fbconfig:%d, renderType:%d, direct:%d\n", | |
499 | (int) a_req->context, (int) a_req->screen, | |
500 | (int) a_req->fbconfig, (int) a_req->renderType, | |
501 | (int) a_req->isDirect); | |
502 | ||
503 | if (!ephyrHostGLXCreateContext(a_req->screen, | |
504 | a_req->fbconfig, | |
505 | a_req->context, | |
506 | a_req->shareList, a_req->renderType, | |
507 | a_req->isDirect, X_GLXCreateNewContext)) { | |
508 | EPHYR_LOG_ERROR("ephyrHostGLXCreateNewContext() failed\n"); | |
509 | goto out; | |
510 | } | |
511 | res = Success; | |
512 | out: | |
513 | EPHYR_LOG("leave\n"); | |
514 | return res; | |
515 | } | |
516 | ||
517 | int | |
518 | ephyrGLXCreateContext(__GLXclientState * cl, GLbyte * pc) | |
519 | { | |
520 | xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; | |
521 | ||
522 | return ephyrGLXCreateContextReal(req, FALSE); | |
523 | } | |
524 | ||
525 | int | |
526 | ephyrGLXCreateContextSwap(__GLXclientState * cl, GLbyte * pc) | |
527 | { | |
528 | xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; | |
529 | ||
530 | return ephyrGLXCreateContextReal(req, TRUE); | |
531 | } | |
532 | ||
533 | int | |
534 | ephyrGLXCreateNewContext(__GLXclientState * cl, GLbyte * pc) | |
535 | { | |
536 | xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; | |
537 | ||
538 | return ephyrGLXCreateNewContextReal(req, FALSE); | |
539 | } | |
540 | ||
541 | int | |
542 | ephyrGLXCreateNewContextSwap(__GLXclientState * cl, GLbyte * pc) | |
543 | { | |
544 | xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; | |
545 | ||
546 | return ephyrGLXCreateNewContextReal(req, TRUE); | |
547 | } | |
548 | ||
549 | static int | |
550 | ephyrGLXDestroyContextReal(__GLXclientState * a_cl, | |
551 | GLbyte * a_pc, Bool a_do_swap) | |
552 | { | |
553 | int res = BadImplementation; | |
554 | ClientPtr client = a_cl->client; | |
555 | xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc; | |
556 | ||
557 | EPHYR_LOG("enter. id:%d\n", (int) req->context); | |
558 | if (!ephyrHostDestroyContext(req->context)) { | |
559 | EPHYR_LOG_ERROR("ephyrHostDestroyContext() failed\n"); | |
560 | client->errorValue = req->context; | |
561 | goto out; | |
562 | } | |
563 | res = Success; | |
564 | ||
565 | out: | |
566 | EPHYR_LOG("leave\n"); | |
567 | return res; | |
568 | } | |
569 | ||
570 | int | |
571 | ephyrGLXDestroyContext(__GLXclientState * a_cl, GLbyte * a_pc) | |
572 | { | |
573 | return ephyrGLXDestroyContextReal(a_cl, a_pc, FALSE); | |
574 | } | |
575 | ||
576 | int | |
577 | ephyrGLXDestroyContextSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
578 | { | |
579 | return ephyrGLXDestroyContextReal(a_cl, a_pc, TRUE); | |
580 | } | |
581 | ||
582 | static int | |
583 | ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLXDrawable write, | |
584 | GLXDrawable read, GLXContextTag ctx, | |
585 | GLXContextTag old_ctx, Bool a_do_swap) | |
586 | { | |
587 | int res = BadImplementation; | |
588 | xGLXMakeCurrentReply reply; | |
589 | DrawablePtr drawableR = NULL, drawableW = NULL; | |
590 | GLXContextTag new_ctx = 0; | |
591 | ||
592 | EPHYR_LOG("enter\n"); | |
593 | res = dixLookupDrawable(&drawableW, write, a_cl->client, 0, DixReadAccess); | |
594 | EPHYR_RETURN_VAL_IF_FAIL(drawableW, BadValue); | |
595 | EPHYR_RETURN_VAL_IF_FAIL(drawableW->pScreen, BadValue); | |
596 | EPHYR_LOG("screen nummber requested:%d\n", drawableW->pScreen->myNum); | |
597 | ||
598 | if (read != write) { | |
599 | res = dixLookupDrawable(&drawableR, read, a_cl->client, 0, | |
600 | DixReadAccess); | |
601 | EPHYR_RETURN_VAL_IF_FAIL(drawableR, BadValue); | |
602 | EPHYR_RETURN_VAL_IF_FAIL(drawableR->pScreen, BadValue); | |
603 | } | |
604 | else { | |
605 | drawableR = drawableW; | |
606 | } | |
607 | ||
608 | if (!ephyrHostGLXMakeCurrent(hostx_get_window(drawableW->pScreen->myNum), | |
609 | hostx_get_window(drawableR->pScreen->myNum), | |
610 | ctx, old_ctx, (int *) &new_ctx)) { | |
611 | EPHYR_LOG_ERROR("ephyrHostGLXMakeCurrent() failed\n"); | |
612 | goto out; | |
613 | } | |
614 | reply = (xGLXMakeCurrentReply) { | |
615 | .type = X_Reply, | |
616 | .sequenceNumber = a_cl->client->sequence, | |
617 | .length = 0, | |
618 | .contextTag = new_ctx | |
619 | }; | |
620 | if (a_do_swap) { | |
621 | __GLX_DECLARE_SWAP_VARIABLES; | |
622 | __GLX_SWAP_SHORT(&reply.sequenceNumber); | |
623 | __GLX_SWAP_INT(&reply.length); | |
624 | __GLX_SWAP_INT(&reply.contextTag); | |
625 | } | |
626 | WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, &reply); | |
627 | ||
628 | res = Success; | |
629 | out: | |
630 | EPHYR_LOG("leave\n"); | |
631 | return res; | |
632 | } | |
633 | ||
634 | int | |
635 | ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc) | |
636 | { | |
637 | xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; | |
638 | return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable, | |
639 | req->context, req->oldContextTag, FALSE); | |
640 | } | |
641 | ||
642 | int | |
643 | ephyrGLXMakeCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
644 | { | |
645 | xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; | |
646 | __GLX_DECLARE_SWAP_VARIABLES; | |
647 | ||
648 | __GLX_SWAP_INT(&req->drawable); | |
649 | __GLX_SWAP_INT(&req->context); | |
650 | __GLX_SWAP_INT(&req->oldContextTag); | |
651 | ||
652 | return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable, | |
653 | req->context, req->oldContextTag, TRUE); | |
654 | } | |
655 | ||
656 | int | |
657 | ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc) | |
658 | { | |
659 | xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc; | |
660 | ||
661 | return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable, | |
662 | req->context, req->oldContextTag, FALSE); | |
663 | } | |
664 | ||
665 | int | |
666 | ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
667 | { | |
668 | xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc; | |
669 | __GLX_DECLARE_SWAP_VARIABLES; | |
670 | ||
671 | __GLX_SWAP_INT(&req->drawable); | |
672 | __GLX_SWAP_INT(&req->readable); | |
673 | __GLX_SWAP_INT(&req->context); | |
674 | __GLX_SWAP_INT(&req->oldContextTag); | |
675 | ||
676 | return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable, | |
677 | req->context, req->oldContextTag, TRUE); | |
678 | } | |
679 | ||
680 | int | |
681 | ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc) | |
682 | { | |
683 | xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc; | |
684 | ||
685 | return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable, | |
686 | req->context, req->oldContextTag, FALSE); | |
687 | } | |
688 | ||
689 | int | |
690 | ephyrGLXMakeContextCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
691 | { | |
692 | xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc; | |
693 | __GLX_DECLARE_SWAP_VARIABLES; | |
694 | ||
695 | __GLX_SWAP_INT(&req->drawable); | |
696 | __GLX_SWAP_INT(&req->readdrawable); | |
697 | __GLX_SWAP_INT(&req->context); | |
698 | __GLX_SWAP_INT(&req->oldContextTag); | |
699 | ||
700 | return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable, | |
701 | req->context, req->oldContextTag, TRUE); | |
702 | } | |
703 | ||
704 | static int | |
705 | ephyrGLXGetStringReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) | |
706 | { | |
707 | ClientPtr client = NULL; | |
708 | int context_tag = 0, name = 0, res = BadImplementation, length = 0; | |
709 | char *string = NULL; | |
710 | ||
711 | __GLX_DECLARE_SWAP_VARIABLES; | |
712 | ||
713 | EPHYR_RETURN_VAL_IF_FAIL(a_cl && a_pc, BadValue); | |
714 | ||
715 | EPHYR_LOG("enter\n"); | |
716 | ||
717 | client = a_cl->client; | |
718 | ||
719 | if (a_do_swap) { | |
720 | __GLX_SWAP_INT(a_pc + 4); | |
721 | __GLX_SWAP_INT(a_pc + __GLX_SINGLE_HDR_SIZE); | |
722 | } | |
723 | context_tag = __GLX_GET_SINGLE_CONTEXT_TAG(a_pc); | |
724 | a_pc += __GLX_SINGLE_HDR_SIZE; | |
725 | name = *(GLenum *) (a_pc + 0); | |
726 | EPHYR_LOG("context_tag:%d, name:%d\n", context_tag, name); | |
727 | if (!ephyrHostGLXGetString(context_tag, name, &string)) { | |
728 | EPHYR_LOG_ERROR("failed to get string from server\n"); | |
729 | goto out; | |
730 | } | |
731 | if (string) { | |
732 | length = strlen(string) + 1; | |
733 | EPHYR_LOG("got string:'%s', size:%d\n", string, length); | |
734 | } | |
735 | else { | |
736 | EPHYR_LOG("got string: string (null)\n"); | |
737 | } | |
738 | __GLX_BEGIN_REPLY(length); | |
739 | __GLX_PUT_SIZE(length); | |
740 | __GLX_SEND_HEADER(); | |
741 | if (a_do_swap) { | |
742 | __GLX_SWAP_REPLY_SIZE(); | |
743 | __GLX_SWAP_REPLY_HEADER(); | |
744 | } | |
745 | WriteToClient(client, length, string); | |
746 | ||
747 | res = Success; | |
748 | out: | |
749 | EPHYR_LOG("leave\n"); | |
750 | return res; | |
751 | } | |
752 | ||
753 | int | |
754 | ephyrGLXGetString(__GLXclientState * a_cl, GLbyte * a_pc) | |
755 | { | |
756 | return ephyrGLXGetStringReal(a_cl, a_pc, FALSE); | |
757 | } | |
758 | ||
759 | int | |
760 | ephyrGLXGetStringSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
761 | { | |
762 | return ephyrGLXGetStringReal(a_cl, a_pc, TRUE); | |
763 | } | |
764 | ||
765 | static int | |
766 | ephyrGLXGetIntegervReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) | |
767 | { | |
768 | int res = BadImplementation; | |
769 | xGLXSingleReq *const req = (xGLXSingleReq *) a_pc; | |
770 | GLenum int_name; | |
771 | int value = 0; | |
772 | GLint answer_buf_room[200]; | |
773 | GLint *buf = NULL; | |
774 | ||
775 | EPHYR_LOG("enter\n"); | |
776 | ||
777 | a_pc += __GLX_SINGLE_HDR_SIZE; | |
778 | ||
779 | int_name = *(GLenum *) (a_pc + 0); | |
780 | if (!ephyrHostGetIntegerValue(req->contextTag, int_name, &value)) { | |
781 | EPHYR_LOG_ERROR("ephyrHostGetIntegerValue() failed\n"); | |
782 | goto out; | |
783 | } | |
784 | buf = __glXGetAnswerBuffer(a_cl, sizeof(value), | |
785 | answer_buf_room, sizeof(answer_buf_room), 4); | |
786 | ||
787 | if (!buf) { | |
788 | EPHYR_LOG_ERROR("failed to allocate reply buffer\n"); | |
789 | res = BadAlloc; | |
790 | goto out; | |
791 | } | |
792 | __glXSendReply(a_cl->client, buf, 1, sizeof(value), GL_FALSE, 0); | |
793 | res = Success; | |
794 | ||
795 | out: | |
796 | EPHYR_LOG("leave\n"); | |
797 | return res; | |
798 | } | |
799 | ||
800 | int | |
801 | ephyrGLXGetIntegerv(__GLXclientState * a_cl, GLbyte * a_pc) | |
802 | { | |
803 | return ephyrGLXGetIntegervReal(a_cl, a_pc, FALSE); | |
804 | } | |
805 | ||
806 | int | |
807 | ephyrGLXGetIntegervSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
808 | { | |
809 | return ephyrGLXGetIntegervReal(a_cl, a_pc, TRUE); | |
810 | } | |
811 | ||
812 | static int | |
813 | ephyrGLXIsDirectReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap) | |
814 | { | |
815 | int res = BadImplementation; | |
816 | ClientPtr client = a_cl->client; | |
817 | xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc; | |
818 | xGLXIsDirectReply reply; | |
819 | int is_direct = 0; | |
820 | ||
821 | EPHYR_RETURN_VAL_IF_FAIL(a_cl && a_pc, FALSE); | |
822 | ||
823 | EPHYR_LOG("enter\n"); | |
824 | ||
825 | if (!ephyrHostIsContextDirect(req->context, (int *) &is_direct)) { | |
826 | EPHYR_LOG_ERROR("ephyrHostIsContextDirect() failed\n"); | |
827 | goto out; | |
828 | } | |
829 | reply = (xGLXIsDirectReply) { | |
830 | .type = X_Reply, | |
831 | .sequenceNumber = client->sequence, | |
832 | .length = 0, | |
833 | .isDirect = is_direct | |
834 | }; | |
835 | ||
836 | WriteToClient(client, sz_xGLXIsDirectReply, &reply); | |
837 | res = Success; | |
838 | ||
839 | out: | |
840 | EPHYR_LOG("leave\n"); | |
841 | return res; | |
842 | } | |
843 | ||
844 | int | |
845 | ephyrGLXIsDirect(__GLXclientState * a_cl, GLbyte * a_pc) | |
846 | { | |
847 | return ephyrGLXIsDirectReal(a_cl, a_pc, FALSE); | |
848 | } | |
849 | ||
850 | int | |
851 | ephyrGLXIsDirectSwap(__GLXclientState * a_cl, GLbyte * a_pc) | |
852 | { | |
853 | return ephyrGLXIsDirectReal(a_cl, a_pc, TRUE); | |
854 | } |