Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / dri / xf86dri.c
CommitLineData
a09e091a
JB
1/**************************************************************************
2
3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4Copyright 2000 VA Linux Systems, Inc.
5All Rights Reserved.
6
7Permission is hereby granted, free of charge, to any person obtaining a
8copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sub license, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice (including the
16next paragraph) shall be included in all copies or substantial portions
17of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27**************************************************************************/
28
29/*
30 * Authors:
31 * Kevin E. Martin <martin@valinux.com>
32 * Jens Owen <jens@tungstengraphics.com>
33 * Rickard E. (Rik) Faith <faith@valinux.com>
34 *
35 */
36
37#ifdef HAVE_XORG_CONFIG_H
38#include <xorg-config.h>
39#endif
40
41#include <string.h>
42
43#include "xf86.h"
44
45#include <X11/X.h>
46#include <X11/Xproto.h>
47#include "misc.h"
48#include "dixstruct.h"
49#include "extnsionst.h"
50#include "extinit.h"
51#include "colormapst.h"
52#include "cursorstr.h"
53#include "scrnintstr.h"
54#include "servermd.h"
55#define _XF86DRI_SERVER_
56#include <X11/dri/xf86driproto.h>
57#include "swaprep.h"
58#include "xf86str.h"
59#include "dri.h"
60#include "sarea.h"
61#include "dristruct.h"
62#include "xf86drm.h"
63#include "protocol-versions.h"
64#include "xf86Extensions.h"
65
66static int DRIErrorBase;
67
68static void XF86DRIResetProc(ExtensionEntry *extEntry);
69
70static unsigned char DRIReqCode = 0;
71
72/*ARGSUSED*/
73static void
74XF86DRIResetProc(ExtensionEntry *extEntry)
75{
76 DRIReset();
77}
78
79static int
80ProcXF86DRIQueryVersion(register ClientPtr client)
81{
82 xXF86DRIQueryVersionReply rep = {
83 .type = X_Reply,
84 .sequenceNumber = client->sequence,
85 .length = 0,
86 .majorVersion = SERVER_XF86DRI_MAJOR_VERSION,
87 .minorVersion = SERVER_XF86DRI_MINOR_VERSION,
88 .patchVersion = SERVER_XF86DRI_PATCH_VERSION
89 };
90
91 REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq);
92 if (client->swapped) {
93 swaps(&rep.sequenceNumber);
94 swapl(&rep.length);
95 swaps(&rep.majorVersion);
96 swaps(&rep.minorVersion);
97 swapl(&rep.patchVersion);
98 }
99 WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), &rep);
100 return Success;
101}
102
103static int
104ProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client)
105{
106 xXF86DRIQueryDirectRenderingCapableReply rep;
107 Bool isCapable;
108
109 REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
110 REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq);
111 if (stuff->screen >= screenInfo.numScreens) {
112 client->errorValue = stuff->screen;
113 return BadValue;
114 }
115
116 if (!DRIQueryDirectRenderingCapable(screenInfo.screens[stuff->screen],
117 &isCapable)) {
118 return BadValue;
119 }
120
121 if (!client->local || client->swapped)
122 isCapable = 0;
123
124 rep = (xXF86DRIQueryDirectRenderingCapableReply) {
125 .type = X_Reply,
126 .sequenceNumber = client->sequence,
127 .length = 0,
128 .isCapable = isCapable
129 };
130
131 if (client->swapped) {
132 swaps(&rep.sequenceNumber);
133 swapl(&rep.length);
134 }
135
136 WriteToClient(client,
137 sizeof(xXF86DRIQueryDirectRenderingCapableReply),
138 &rep);
139 return Success;
140}
141
142static int
143ProcXF86DRIOpenConnection(register ClientPtr client)
144{
145 xXF86DRIOpenConnectionReply rep;
146 drm_handle_t hSAREA;
147 char *busIdString;
148 CARD32 busIdStringLength = 0;
149
150 REQUEST(xXF86DRIOpenConnectionReq);
151 REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq);
152 if (stuff->screen >= screenInfo.numScreens) {
153 client->errorValue = stuff->screen;
154 return BadValue;
155 }
156
157 if (!DRIOpenConnection(screenInfo.screens[stuff->screen],
158 &hSAREA, &busIdString)) {
159 return BadValue;
160 }
161
162 if (busIdString)
163 busIdStringLength = strlen(busIdString);
164
165 rep = (xXF86DRIOpenConnectionReply) {
166 .type = X_Reply,
167 .sequenceNumber = client->sequence,
168 .length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) -
169 SIZEOF(xGenericReply) +
170 pad_to_int32(busIdStringLength)),
171 .busIdStringLength = busIdStringLength,
172
173 .hSAREALow = (CARD32) (hSAREA & 0xffffffff),
174#if defined(LONG64) && !defined(__linux__)
175 .hSAREAHigh = (CARD32) (hSAREA >> 32),
176#else
177 .hSAREAHigh = 0
178#endif
179 };
180
181 WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), &rep);
182 if (busIdStringLength)
183 WriteToClient(client, busIdStringLength, busIdString);
184 return Success;
185}
186
187static int
188ProcXF86DRIAuthConnection(register ClientPtr client)
189{
190 xXF86DRIAuthConnectionReply rep = {
191 .type = X_Reply,
192 .sequenceNumber = client->sequence,
193 .length = 0,
194 .authenticated = 1
195 };
196
197 REQUEST(xXF86DRIAuthConnectionReq);
198 REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq);
199 if (stuff->screen >= screenInfo.numScreens) {
200 client->errorValue = stuff->screen;
201 return BadValue;
202 }
203
204 if (!DRIAuthConnection(screenInfo.screens[stuff->screen], stuff->magic)) {
205 ErrorF("Failed to authenticate %lu\n", (unsigned long) stuff->magic);
206 rep.authenticated = 0;
207 }
208 WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), &rep);
209 return Success;
210}
211
212static int
213ProcXF86DRICloseConnection(register ClientPtr client)
214{
215 REQUEST(xXF86DRICloseConnectionReq);
216 REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq);
217 if (stuff->screen >= screenInfo.numScreens) {
218 client->errorValue = stuff->screen;
219 return BadValue;
220 }
221
222 DRICloseConnection(screenInfo.screens[stuff->screen]);
223
224 return Success;
225}
226
227static int
228ProcXF86DRIGetClientDriverName(register ClientPtr client)
229{
230 xXF86DRIGetClientDriverNameReply rep = {
231 .type = X_Reply,
232 .sequenceNumber = client->sequence,
233 .clientDriverNameLength = 0
234 };
235 char *clientDriverName;
236
237 REQUEST(xXF86DRIGetClientDriverNameReq);
238 REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq);
239 if (stuff->screen >= screenInfo.numScreens) {
240 client->errorValue = stuff->screen;
241 return BadValue;
242 }
243
244 DRIGetClientDriverName(screenInfo.screens[stuff->screen],
245 (int *) &rep.ddxDriverMajorVersion,
246 (int *) &rep.ddxDriverMinorVersion,
247 (int *) &rep.ddxDriverPatchVersion,
248 &clientDriverName);
249
250 if (clientDriverName)
251 rep.clientDriverNameLength = strlen(clientDriverName);
252 rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) -
253 SIZEOF(xGenericReply) +
254 pad_to_int32(rep.clientDriverNameLength));
255
256 WriteToClient(client, sizeof(xXF86DRIGetClientDriverNameReply), &rep);
257 if (rep.clientDriverNameLength)
258 WriteToClient(client, rep.clientDriverNameLength, clientDriverName);
259 return Success;
260}
261
262static int
263ProcXF86DRICreateContext(register ClientPtr client)
264{
265 xXF86DRICreateContextReply rep = {
266 .type = X_Reply,
267 .sequenceNumber = client->sequence,
268 .length = 0
269 };
270 ScreenPtr pScreen;
271
272 REQUEST(xXF86DRICreateContextReq);
273 REQUEST_SIZE_MATCH(xXF86DRICreateContextReq);
274 if (stuff->screen >= screenInfo.numScreens) {
275 client->errorValue = stuff->screen;
276 return BadValue;
277 }
278
279 pScreen = screenInfo.screens[stuff->screen];
280
281 if (!DRICreateContext(pScreen,
282 NULL,
283 stuff->context, (drm_context_t *) &rep.hHWContext)) {
284 return BadValue;
285 }
286
287 WriteToClient(client, sizeof(xXF86DRICreateContextReply), &rep);
288 return Success;
289}
290
291static int
292ProcXF86DRIDestroyContext(register ClientPtr client)
293{
294 REQUEST(xXF86DRIDestroyContextReq);
295 REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq);
296 if (stuff->screen >= screenInfo.numScreens) {
297 client->errorValue = stuff->screen;
298 return BadValue;
299 }
300
301 if (!DRIDestroyContext(screenInfo.screens[stuff->screen], stuff->context)) {
302 return BadValue;
303 }
304
305 return Success;
306}
307
308static int
309ProcXF86DRICreateDrawable(ClientPtr client)
310{
311 xXF86DRICreateDrawableReply rep = {
312 .type = X_Reply,
313 .sequenceNumber = client->sequence,
314 .length = 0
315 };
316 DrawablePtr pDrawable;
317 int rc;
318
319 REQUEST(xXF86DRICreateDrawableReq);
320 REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq);
321 if (stuff->screen >= screenInfo.numScreens) {
322 client->errorValue = stuff->screen;
323 return BadValue;
324 }
325
326 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
327 DixReadAccess);
328 if (rc != Success)
329 return rc;
330
331 if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client,
332 pDrawable, (drm_drawable_t *) &rep.hHWDrawable)) {
333 return BadValue;
334 }
335
336 WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), &rep);
337 return Success;
338}
339
340static int
341ProcXF86DRIDestroyDrawable(register ClientPtr client)
342{
343 REQUEST(xXF86DRIDestroyDrawableReq);
344 DrawablePtr pDrawable;
345 int rc;
346
347 REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq);
348
349 if (stuff->screen >= screenInfo.numScreens) {
350 client->errorValue = stuff->screen;
351 return BadValue;
352 }
353
354 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
355 DixReadAccess);
356 if (rc != Success)
357 return rc;
358
359 if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client,
360 pDrawable)) {
361 return BadValue;
362 }
363
364 return Success;
365}
366
367static int
368ProcXF86DRIGetDrawableInfo(register ClientPtr client)
369{
370 xXF86DRIGetDrawableInfoReply rep = {
371 .type = X_Reply,
372 .sequenceNumber = client->sequence,
373 .length = 0
374 };
375 DrawablePtr pDrawable;
376 int X, Y, W, H;
377 drm_clip_rect_t *pClipRects, *pClippedRects;
378 drm_clip_rect_t *pBackClipRects;
379 int backX, backY, rc;
380
381 REQUEST(xXF86DRIGetDrawableInfoReq);
382 REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq);
383 if (stuff->screen >= screenInfo.numScreens) {
384 client->errorValue = stuff->screen;
385 return BadValue;
386 }
387
388 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
389 DixReadAccess);
390 if (rc != Success)
391 return rc;
392
393 if (!DRIGetDrawableInfo(screenInfo.screens[stuff->screen],
394 pDrawable,
395 (unsigned int *) &rep.drawableTableIndex,
396 (unsigned int *) &rep.drawableTableStamp,
397 (int *) &X,
398 (int *) &Y,
399 (int *) &W,
400 (int *) &H,
401 (int *) &rep.numClipRects,
402 &pClipRects,
403 &backX,
404 &backY,
405 (int *) &rep.numBackClipRects, &pBackClipRects)) {
406 return BadValue;
407 }
408
409 rep.drawableX = X;
410 rep.drawableY = Y;
411 rep.drawableWidth = W;
412 rep.drawableHeight = H;
413 rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - SIZEOF(xGenericReply));
414
415 rep.backX = backX;
416 rep.backY = backY;
417
418 if (rep.numBackClipRects)
419 rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects;
420
421 pClippedRects = pClipRects;
422
423 if (rep.numClipRects) {
424 /* Clip cliprects to screen dimensions (redirected windows) */
425 pClippedRects = malloc(rep.numClipRects * sizeof(drm_clip_rect_t));
426
427 if (pClippedRects) {
428 ScreenPtr pScreen = screenInfo.screens[stuff->screen];
429 int i, j;
430
431 for (i = 0, j = 0; i < rep.numClipRects; i++) {
432 pClippedRects[j].x1 = max(pClipRects[i].x1, 0);
433 pClippedRects[j].y1 = max(pClipRects[i].y1, 0);
434 pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width);
435 pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height);
436
437 if (pClippedRects[j].x1 < pClippedRects[j].x2 &&
438 pClippedRects[j].y1 < pClippedRects[j].y2) {
439 j++;
440 }
441 }
442
443 rep.numClipRects = j;
444 }
445 else {
446 rep.numClipRects = 0;
447 }
448
449 rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects;
450 }
451
452 rep.length = bytes_to_int32(rep.length);
453
454 WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), &rep);
455
456 if (rep.numClipRects) {
457 WriteToClient(client,
458 sizeof(drm_clip_rect_t) * rep.numClipRects,
459 pClippedRects);
460 free(pClippedRects);
461 }
462
463 if (rep.numBackClipRects) {
464 WriteToClient(client,
465 sizeof(drm_clip_rect_t) * rep.numBackClipRects,
466 pBackClipRects);
467 }
468
469 return Success;
470}
471
472static int
473ProcXF86DRIGetDeviceInfo(register ClientPtr client)
474{
475 xXF86DRIGetDeviceInfoReply rep = {
476 .type = X_Reply,
477 .sequenceNumber = client->sequence,
478 .length = 0
479 };
480 drm_handle_t hFrameBuffer;
481 void *pDevPrivate;
482
483 REQUEST(xXF86DRIGetDeviceInfoReq);
484 REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq);
485 if (stuff->screen >= screenInfo.numScreens) {
486 client->errorValue = stuff->screen;
487 return BadValue;
488 }
489
490 if (!DRIGetDeviceInfo(screenInfo.screens[stuff->screen],
491 &hFrameBuffer,
492 (int *) &rep.framebufferOrigin,
493 (int *) &rep.framebufferSize,
494 (int *) &rep.framebufferStride,
495 (int *) &rep.devPrivateSize, &pDevPrivate)) {
496 return BadValue;
497 }
498
499 rep.hFrameBufferLow = (CARD32) (hFrameBuffer & 0xffffffff);
500#if defined(LONG64) && !defined(__linux__)
501 rep.hFrameBufferHigh = (CARD32) (hFrameBuffer >> 32);
502#else
503 rep.hFrameBufferHigh = 0;
504#endif
505
506 if (rep.devPrivateSize) {
507 rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) -
508 SIZEOF(xGenericReply) +
509 pad_to_int32(rep.devPrivateSize));
510 }
511
512 WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), &rep);
513 if (rep.length) {
514 WriteToClient(client, rep.devPrivateSize, pDevPrivate);
515 }
516 return Success;
517}
518
519static int
520ProcXF86DRIDispatch(register ClientPtr client)
521{
522 REQUEST(xReq);
523
524 switch (stuff->data) {
525 case X_XF86DRIQueryVersion:
526 return ProcXF86DRIQueryVersion(client);
527 case X_XF86DRIQueryDirectRenderingCapable:
528 return ProcXF86DRIQueryDirectRenderingCapable(client);
529 }
530
531 if (!client->local)
532 return DRIErrorBase + XF86DRIClientNotLocal;
533
534 switch (stuff->data) {
535 case X_XF86DRIOpenConnection:
536 return ProcXF86DRIOpenConnection(client);
537 case X_XF86DRICloseConnection:
538 return ProcXF86DRICloseConnection(client);
539 case X_XF86DRIGetClientDriverName:
540 return ProcXF86DRIGetClientDriverName(client);
541 case X_XF86DRICreateContext:
542 return ProcXF86DRICreateContext(client);
543 case X_XF86DRIDestroyContext:
544 return ProcXF86DRIDestroyContext(client);
545 case X_XF86DRICreateDrawable:
546 return ProcXF86DRICreateDrawable(client);
547 case X_XF86DRIDestroyDrawable:
548 return ProcXF86DRIDestroyDrawable(client);
549 case X_XF86DRIGetDrawableInfo:
550 return ProcXF86DRIGetDrawableInfo(client);
551 case X_XF86DRIGetDeviceInfo:
552 return ProcXF86DRIGetDeviceInfo(client);
553 case X_XF86DRIAuthConnection:
554 return ProcXF86DRIAuthConnection(client);
555 /* {Open,Close}FullScreen are deprecated now */
556 default:
557 return BadRequest;
558 }
559}
560
561static int
562SProcXF86DRIQueryVersion(register ClientPtr client)
563{
564 REQUEST(xXF86DRIQueryVersionReq);
565 swaps(&stuff->length);
566 return ProcXF86DRIQueryVersion(client);
567}
568
569static int
570SProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client)
571{
572 REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
573 swaps(&stuff->length);
574 swapl(&stuff->screen);
575 return ProcXF86DRIQueryDirectRenderingCapable(client);
576}
577
578static int
579SProcXF86DRIDispatch(register ClientPtr client)
580{
581 REQUEST(xReq);
582
583 /*
584 * Only local clients are allowed DRI access, but remote clients still need
585 * these requests to find out cleanly.
586 */
587 switch (stuff->data) {
588 case X_XF86DRIQueryVersion:
589 return SProcXF86DRIQueryVersion(client);
590 case X_XF86DRIQueryDirectRenderingCapable:
591 return SProcXF86DRIQueryDirectRenderingCapable(client);
592 default:
593 return DRIErrorBase + XF86DRIClientNotLocal;
594 }
595}
596
597void
598XFree86DRIExtensionInit(void)
599{
600 ExtensionEntry *extEntry;
601
602#ifdef XF86DRI_EVENTS
603 EventType = CreateNewResourceType(XF86DRIFreeEvents, "DRIEvent");
604#endif
605
606 if (DRIExtensionInit() &&
607#ifdef XF86DRI_EVENTS
608 EventType && ScreenPrivateIndex != -1 &&
609#endif
610 (extEntry = AddExtension(XF86DRINAME,
611 XF86DRINumberEvents,
612 XF86DRINumberErrors,
613 ProcXF86DRIDispatch,
614 SProcXF86DRIDispatch,
615 XF86DRIResetProc, StandardMinorOpcode))) {
616 DRIReqCode = (unsigned char) extEntry->base;
617 DRIErrorBase = extEntry->errorBase;
618 }
619}