2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Code to allow the softpipe code to write to X windows/buffers.
29 * This is a bit of a hack for now. We've basically got two different
30 * abstractions for color buffers: gl_renderbuffer and pipe_surface.
31 * They'll need to get merged someday...
32 * For now, they're separate things that point to each other.
37 #include "glxheader.h"
39 #include "main/context.h"
40 #include "main/imports.h"
41 #include "main/macros.h"
43 #include "pipe/p_context.h"
44 #include "pipe/p_defines.h"
45 #include "pipe/p_winsys.h"
46 #include "pipe/softpipe/sp_context.h"
47 #include "pipe/softpipe/sp_clear.h"
48 #include "pipe/softpipe/sp_tile_cache.h"
49 #include "pipe/softpipe/sp_surface.h"
50 #include "state_tracker/st_context.h"
54 * Dithering kernels and lookup tables.
57 const int xmesa_kernel8
[DITH_DY
* DITH_DX
] = {
58 0 * MAXC
, 8 * MAXC
, 2 * MAXC
, 10 * MAXC
,
59 12 * MAXC
, 4 * MAXC
, 14 * MAXC
, 6 * MAXC
,
60 3 * MAXC
, 11 * MAXC
, 1 * MAXC
, 9 * MAXC
,
61 15 * MAXC
, 7 * MAXC
, 13 * MAXC
, 5 * MAXC
,
64 const int xmesa_kernel1
[16] = {
65 0*47, 9*47, 4*47, 12*47, /* 47 = (255*3)/16 */
66 6*47, 2*47, 14*47, 8*47,
67 10*47, 1*47, 5*47, 11*47,
68 7*47, 13*47, 3*47, 15*47
77 if (y >= ps->height) \
79 if (x + w > ps->width) \
81 if (y + h > ps->height) \
88 * The following functions are used to trap XGetImage() calls which
89 * generate BadMatch errors if the drawable isn't mapped.
93 static int caught_xgetimage_error
= 0;
94 static int (*old_xerror_handler
)( XMesaDisplay
*dpy
, XErrorEvent
*ev
);
95 static unsigned long xgetimage_serial
;
98 * This is the error handler which will be called if XGetImage fails.
100 static int xgetimage_error_handler( XMesaDisplay
*dpy
, XErrorEvent
*ev
)
102 if (ev
->serial
==xgetimage_serial
&& ev
->error_code
==BadMatch
) {
103 /* caught the expected error */
104 caught_xgetimage_error
= 0;
107 /* call the original X error handler, if any. otherwise ignore */
108 if (old_xerror_handler
) {
109 (*old_xerror_handler
)( dpy
, ev
);
117 * Call this right before XGetImage to setup error trap.
119 static void catch_xgetimage_errors( XMesaDisplay
*dpy
)
121 xgetimage_serial
= NextRequest( dpy
);
122 old_xerror_handler
= XSetErrorHandler( xgetimage_error_handler
);
123 caught_xgetimage_error
= 0;
128 * Call this right after XGetImage to check if an error occured.
130 static int check_xgetimage_errors( void )
132 /* restore old handler */
133 (void) XSetErrorHandler( old_xerror_handler
);
134 /* return 0=no error, 1=error caught */
135 return caught_xgetimage_error
;
141 * Wrapper for XGetImage() that catches BadMatch errors that can occur
142 * when the window is unmapped or the x/y/w/h extend beyond the window
144 * If build into xserver, wrap the internal GetImage method.
147 xget_image(XMesaDisplay
*dpy
, Drawable d
, int x
, int y
, uint w
, uint h
)
150 uint bpp
= 4; /* XXX fix this */
151 XMesaImage
*ximage
= (XMesaImage
*) malloc(sizeof(XMesaImage
));
153 ximage
->data
= malloc(width
* height
* bpp
);
155 (*dpy
->GetImage
)(d
, x
, y
, w
, h
, ZPixmap
, ~0L, (pointer
)ximage
->data
);
158 ximage
->bytes_per_row
= w
* bpp
;
163 catch_xgetimage_errors(dpy
);
164 ximage
= XGetImage(dpy
, d
, x
, y
, w
, h
, AllPlanes
, ZPixmap
);
165 error
= check_xgetimage_errors();
173 * Return raw pixels from pixmap or XImage.
176 xmesa_get_tile(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
177 uint x
, uint y
, uint w
, uint h
, void *p
, int dst_stride
)
180 struct xmesa_surface
*xms
= xmesa_surface(ps
);
181 XMesaImage
*ximage
= NULL
;
182 ubyte
*dst
= (ubyte
*) p
;
185 if (!xms
->drawable
&& !xms
->ximage
) {
186 /* not an X surface */
187 softpipe_get_tile(pipe
, ps
, x
, y
, w
, h
, p
, dst_stride
);
194 /* XImage = pixmap data */
195 assert(xms
->drawable
);
196 ximage
= xget_image(xms
->display
, xms
->drawable
, x
, y
, w
, h
);
202 ximage
= xms
->ximage
;
205 /* this could be optimized/simplified */
206 switch (ps
->format
) {
207 case PIPE_FORMAT_U_A8_R8_G8_B8
:
211 for (i
= 0; i
< h
; i
++) {
212 memcpy(dst
, ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 4, 4 * w
);
216 case PIPE_FORMAT_U_R5_G6_B5
:
220 for (i
= 0; i
< h
; i
++) {
221 memcpy(dst
, ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 2, 4 * 2);
230 XMesaDestroyImage(ximage
);
236 * Put raw pixels into pixmap or XImage.
239 xmesa_put_tile(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
240 uint x
, uint y
, uint w
, uint h
, const void *p
, int src_stride
)
243 struct xmesa_surface
*xms
= xmesa_surface(ps
);
244 const ubyte
*src
= (const ubyte
*) p
;
247 if (!xms
->drawable
&& !xms
->ximage
) {
248 /* not an X surface */
249 softpipe_put_tile(pipe
, ps
, x
, y
, w
, h
, p
, src_stride
);
257 ximage
= xms
->ximage
;
261 /* this could be optimized/simplified */
262 switch (ps
->format
) {
263 case PIPE_FORMAT_U_A8_R8_G8_B8
:
267 dst
= ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 4;
268 for (i
= 0; i
< h
; i
++) {
269 memcpy(dst
, src
, w
* 4);
270 dst
+= ximage
->bytes_per_line
;
274 case PIPE_FORMAT_U_R5_G6_B5
:
278 dst
= ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 2;
279 for (i
= 0; i
< h
; i
++) {
280 memcpy(dst
, src
, w
* 2);
281 dst
+= ximage
->bytes_per_line
;
290 /* put to pixmap/window */
291 /* Create temp XImage for data */
293 ximage
= XMesaCreateImage(GET_VISUAL_DEPTH(v
), w
, h
, p
);
295 XVisualInfo
*visinfo
= xms
->xrb
->Parent
->xm_visual
->visinfo
;
296 ximage
= XCreateImage(xms
->display
,
299 ZPixmap
, 0, /* format, offset */
300 (char *) p
, /* data */
301 w
, h
, /* width, height */
303 0); /* bytes_per_line */
306 /* send XImage data to pixmap */
307 XPutImage(xms
->display
, xms
->drawable
, xms
->gc
,
308 ximage
, 0, 0, x
, y
, w
, h
);
310 ximage
->data
= NULL
; /* prevents freeing user data at 'p' */
311 XMesaDestroyImage(ximage
);
317 xmesa_get_tile_rgba(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
318 uint x
, uint y
, uint w
, uint h
, float *pixels
)
321 struct xmesa_surface
*xms
= xmesa_surface(ps
);
322 XMesaImage
*ximage
= NULL
;
323 float *pRow
= pixels
;
326 if (!xms
->drawable
&& !xms
->ximage
) {
327 /* not an X surface */
328 softpipe_get_tile_rgba(pipe
, ps
, x
, y
, w
, h
, pixels
);
335 /* XImage = pixmap data */
336 assert(xms
->drawable
);
337 ximage
= xget_image(xms
->display
, xms
->drawable
, x
, y
, w
, h
);
343 ximage
= xms
->ximage
;
346 switch (ps
->format
) {
347 case PIPE_FORMAT_U_A8_R8_G8_B8
:
350 = (uint
*) (ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 4);
351 for (i
= 0; i
< h
; i
++) {
353 for (j
= 0; j
< w
; j
++) {
355 ubyte r
= ((pix
>> 16) & 0xff);
356 ubyte g
= ((pix
>> 8) & 0xff);
357 ubyte b
= ( pix
& 0xff);
358 ubyte a
= ((pix
>> 24) & 0xff);
359 p
[0] = UBYTE_TO_FLOAT(r
);
360 p
[1] = UBYTE_TO_FLOAT(g
);
361 p
[2] = UBYTE_TO_FLOAT(b
);
362 p
[3] = UBYTE_TO_FLOAT(a
);
365 src
+= ximage
->width
;
370 case PIPE_FORMAT_U_B8_G8_R8_A8
:
373 = (uint
*) (ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 4);
374 for (i
= 0; i
< h
; i
++) {
376 for (j
= 0; j
< w
; j
++) {
378 ubyte r
= ((pix
>> 8) & 0xff);
379 ubyte g
= ((pix
>> 16) & 0xff);
380 ubyte b
= ((pix
>> 24) & 0xff);
381 ubyte a
= ( pix
& 0xff);
382 p
[0] = UBYTE_TO_FLOAT(r
);
383 p
[1] = UBYTE_TO_FLOAT(g
);
384 p
[2] = UBYTE_TO_FLOAT(b
);
385 p
[3] = UBYTE_TO_FLOAT(a
);
388 src
+= ximage
->width
;
393 case PIPE_FORMAT_U_R5_G6_B5
:
396 = (ushort
*) (ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 2);
397 for (i
= 0; i
< h
; i
++) {
399 for (j
= 0; j
< w
; j
++) {
401 ubyte r
= (pix
>> 8) | ((pix
>> 13) & 0x7);
402 ubyte g
= (pix
>> 3) | ((pix
>> 9) & 0x3);
403 ubyte b
= ((pix
& 0x1f) << 3) | ((pix
>> 2) & 0x3);
404 p
[0] = UBYTE_TO_FLOAT(r
);
405 p
[1] = UBYTE_TO_FLOAT(g
);
406 p
[2] = UBYTE_TO_FLOAT(b
);
410 src
+= ximage
->width
;
416 fprintf(stderr
, "Bad format in xmesa_get_tile_rgba()\n");
421 XMesaDestroyImage(ximage
);
427 xmesa_put_tile_rgba(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
428 uint x
, uint y
, uint w
, uint h
, const float *pixels
)
430 const uint x0
= x
, y0
= y
, w0
= w
;
431 struct xmesa_surface
*xms
= xmesa_surface(ps
);
435 if (!xms
->drawable
&& !xms
->ximage
) {
436 /* not an X surface */
437 softpipe_put_tile_rgba(pipe
, ps
, x
, y
, w
, h
, pixels
);
444 /* create temp XImage */
445 char *data
= (char *) malloc(w
* h
* 4);
447 ximage
= XMesaCreateImage(GET_VISUAL_DEPTH(v
), w
, h
, data
);
449 XVisualInfo
*visinfo
= xms
->xrb
->Parent
->xm_visual
->visinfo
;
450 ximage
= XCreateImage(xms
->display
,
453 ZPixmap
, 0, /* format, offset */
455 w
, h
, /* width, height */
457 0); /* bytes_per_line */
462 ximage
= xms
->ximage
;
465 /* convert floats to ximage's format */
466 switch (ps
->format
) {
467 case PIPE_FORMAT_U_A8_R8_G8_B8
:
470 = (uint
*) (ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 4);
471 const float *pRow
= pixels
;
472 for (i
= 0; i
< h
; i
++) {
473 const float *p
= pRow
;
474 for (j
= 0; j
< w
; j
++) {
476 UNCLAMPED_FLOAT_TO_UBYTE(r
, p
[0]);
477 UNCLAMPED_FLOAT_TO_UBYTE(g
, p
[1]);
478 UNCLAMPED_FLOAT_TO_UBYTE(b
, p
[2]);
479 UNCLAMPED_FLOAT_TO_UBYTE(a
, p
[3]);
480 dst
[j
] = PACK_8A8R8G8B(r
, g
, b
, a
);
483 dst
+= ximage
->width
;
488 case PIPE_FORMAT_U_B8_G8_R8_A8
:
491 = (uint
*) (ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 4);
492 const float *pRow
= pixels
;
493 for (i
= 0; i
< h
; i
++) {
494 const float *p
= pRow
;
495 for (j
= 0; j
< w
; j
++) {
497 UNCLAMPED_FLOAT_TO_UBYTE(r
, p
[0]);
498 UNCLAMPED_FLOAT_TO_UBYTE(g
, p
[1]);
499 UNCLAMPED_FLOAT_TO_UBYTE(b
, p
[2]);
500 UNCLAMPED_FLOAT_TO_UBYTE(a
, p
[3]);
501 dst
[j
] = PACK_8B8G8R8A(r
, g
, b
, a
);
504 dst
+= ximage
->width
;
509 case PIPE_FORMAT_U_R5_G6_B5
:
512 (ushort
*) (ximage
->data
+ y
* ximage
->bytes_per_line
+ x
* 2);
513 const float *pRow
= pixels
;
514 for (i
= 0; i
< h
; i
++) {
515 const float *p
= pRow
;
516 for (j
= 0; j
< w
; j
++) {
518 UNCLAMPED_FLOAT_TO_UBYTE(r
, p
[0]);
519 UNCLAMPED_FLOAT_TO_UBYTE(g
, p
[1]);
520 UNCLAMPED_FLOAT_TO_UBYTE(b
, p
[2]);
521 dst
[j
] = PACK_5R6G5B(r
, g
, b
);
524 dst
+= ximage
->width
;
531 fprintf(stderr
, "Bad format in xmesa_put_tile_rgba()\n");
536 /* send XImage data to pixmap */
537 XPutImage(xms
->display
, xms
->drawable
, xms
->gc
,
538 ximage
, 0, 0, x0
, y0
, w
, h
);
542 XMesaDestroyImage(ximage
);
548 clear_pixmap_surface(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
551 struct xmesa_surface
*xms
= xmesa_surface(ps
);
553 assert(xms
->display
);
554 assert(xms
->drawable
);
556 XMesaSetForeground( xms
->display
, xms
->gc
, value
);
557 XMesaFillRectangle( xms
->display
, xms
->drawable
, xms
->gc
,
558 0, 0, ps
->width
, ps
->height
);
562 clear_nbit_ximage_surface(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
565 struct xmesa_surface
*xms
= xmesa_surface(ps
);
566 int width
= xms
->surface
.width
;
567 int height
= xms
->surface
.height
;
569 for (j
= 0; j
< height
; j
++) {
570 for (i
= 0; i
< width
; i
++) {
571 XMesaPutPixel(xms
->ximage
, i
, j
, value
);
577 clear_8bit_ximage_surface(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
580 struct xmesa_surface
*xms
= xmesa_surface(ps
);
581 memset(xms
->ximage
->data
,
583 xms
->ximage
->bytes_per_line
* xms
->ximage
->height
);
587 clear_16bit_ximage_surface(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
590 struct xmesa_surface
*xms
= xmesa_surface(ps
);
591 const int n
= xms
->ximage
->width
* xms
->ximage
->height
;
592 ushort
*dst
= (ushort
*) xms
->ximage
->data
;
594 for (i
= 0; i
< n
; i
++) {
600 /* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
602 clear_24bit_ximage_surface(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
605 struct xmesa_surface
*xms
= xmesa_surface(ps
);
606 const ubyte r
= (value
) & 0xff;
607 const ubyte g
= (value
>> 8) & 0xff;
608 const ubyte b
= (value
>> 16) & 0xff;
610 if (r
== g
&& g
== b
) {
611 /* same value for all three components (gray) */
612 memset(xms
->ximage
->data
, r
,
613 xms
->ximage
->bytes_per_line
* xms
->ximage
->height
);
616 /* non-gray clear color */
617 const int n
= xms
->ximage
->width
* xms
->ximage
->height
;
619 bgr_t
*ptr3
= (bgr_t
*) xms
->ximage
->data
;
620 for (i
= 0; i
< n
; i
++) {
630 clear_32bit_ximage_surface(struct pipe_context
*pipe
, struct pipe_surface
*ps
,
633 struct xmesa_surface
*xms
= xmesa_surface(ps
);
637 memset(xms
->ximage
->data
, value
,
638 xms
->ximage
->bytes_per_line
* xms
->ximage
->height
);
641 const int n
= xms
->ximage
->width
* xms
->ximage
->height
;
642 uint
*dst
= (uint
*) xms
->ximage
->data
;
644 for (i
= 0; i
< n
; i
++)
653 * Called to create a pipe_surface for each X renderbuffer.
654 * Note: this is being used instead of pipe->surface_alloc() since we
655 * have special/unique quad read/write functions for X.
657 struct pipe_surface
*
658 xmesa_new_color_surface(struct pipe_winsys
*winsys
, GLuint pipeFormat
)
660 struct xmesa_surface
*xms
= CALLOC_STRUCT(xmesa_surface
);
664 xms
->surface
.format
= pipeFormat
;
665 xms
->surface
.refcount
= 1;
666 xms
->surface
.winsys
= winsys
;
668 /* Note, the buffer we allocate doesn't actually have any storage
669 * since we're drawing into an XImage or Pixmap.
670 * The surface's size will get set in the xmesa_alloc_front/back_storage()
673 xms
->surface
.buffer
= winsys
->buffer_create(winsys
, 0x0);
675 return &xms
->surface
;
680 * Called via pipe->surface_alloc() to create new surfaces (textures,
681 * renderbuffers, etc.
683 struct pipe_surface
*
684 xmesa_surface_alloc(struct pipe_context
*pipe
, GLuint pipeFormat
)
686 struct xmesa_surface
*xms
= CALLOC_STRUCT(xmesa_surface
);
691 xms
->surface
.format
= pipeFormat
;
692 xms
->surface
.refcount
= 1;
693 xms
->surface
.winsys
= pipe
->winsys
;
695 return &xms
->surface
;
700 * Called via pipe->clear() to clear entire surface to a certain value.
701 * If the surface is not an X pixmap or XImage, pass the call to
705 xmesa_clear(struct pipe_context
*pipe
, struct pipe_surface
*ps
, uint value
)
707 struct xmesa_surface
*xms
= xmesa_surface(ps
);
709 /* XXX actually, we should just discard any cached tiles from this
710 * surface since we don't want to accidentally re-use them after clearing.
712 pipe
->flush(pipe
, 0);
715 struct softpipe_context
*sp
= softpipe_context(pipe
);
716 if (ps
== sp_tile_cache_get_surface(sp
, sp
->cbuf_cache
[0])) {
718 clear
[0] = 0.2; /* XXX hack */
722 sp_tile_cache_clear(sp
->cbuf_cache
[0], clear
);
727 (void) clear_8bit_ximage_surface
;
728 (void) clear_24bit_ximage_surface
;
732 /* back color buffer */
733 switch (xms
->surface
.format
) {
734 case PIPE_FORMAT_U_R5_G6_B5
:
735 clear_16bit_ximage_surface(pipe
, ps
, value
);
737 case PIPE_FORMAT_U_A8_R8_G8_B8
:
738 case PIPE_FORMAT_U_B8_G8_R8_A8
:
739 clear_32bit_ximage_surface(pipe
, ps
, value
);
742 clear_nbit_ximage_surface(pipe
, ps
, value
);
746 else if (xms
->drawable
) {
747 /* front color buffer */
748 clear_pixmap_surface(pipe
, ps
, value
);
751 /* other kind of buffer */
752 softpipe_clear(pipe
, ps
, value
);
757 /** XXX unfinished sketch... */
758 struct pipe_surface
*
759 xmesa_create_front_surface(XMesaVisual vis
, Window win
)
761 struct xmesa_surface
*xms
= CALLOC_STRUCT(xmesa_surface
);
766 xms
->display
= vis
->display
;
769 xms
->surface
.format
= PIPE_FORMAT_U_A8_R8_G8_B8
;
770 xms
->surface
.refcount
= 1;
772 xms
->surface
.region
= pipe
->winsys
->region_alloc(pipe
->winsys
,
775 return &xms
->surface
;