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 * All the XMesa* API functions.
33 * The window coordinate system origin (0,0) is in the lower-left corner
34 * of the window. X11's window coordinate origin is in the upper-left
35 * corner of the window. Therefore, most drawing functions in this
36 * file have to flip Y coordinates.
38 * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
39 * in support for the MIT Shared Memory extension. If enabled, when you
40 * use an Ximage for the back buffer in double buffered mode, the "swap"
41 * operation will be faster. You must also link with -lXext.
43 * Byte swapping: If the Mesa host and the X display use a different
44 * byte order then there's some trickiness to be aware of when using
45 * XImages. The byte ordering used for the XImage is that of the X
46 * display, not the Mesa host.
47 * The color-to-pixel encoding for True/DirectColor must be done
48 * according to the display's visual red_mask, green_mask, and blue_mask.
49 * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
50 * do byte swapping if needed. If one wants to directly "poke" the pixel
51 * into the XImage's buffer then the pixel must be byte swapped first. In
52 * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
53 * and use XPutPixel everywhere except in the implementation of
54 * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so
55 * instead of using XPutPixel we "poke" our values after byte-swapping
56 * the clear pixel value if needed.
65 #include "glxheader.h"
67 #include "main/context.h"
68 #include "main/extensions.h"
69 #include "main/framebuffer.h"
70 #include "main/imports.h"
71 #include "main/macros.h"
72 #include "main/renderbuffer.h"
73 #include "main/teximage.h"
74 #include "glapi/glthread.h"
75 #include "swrast/swrast.h"
76 #include "swrast_setup/swrast_setup.h"
79 #include "tnl/t_context.h"
80 #include "tnl/t_pipeline.h"
81 #include "drivers/common/driverfuncs.h"
82 #include "drivers/common/meta.h"
85 * Global X driver lock
87 _glthread_Mutex _xmesa_lock
;
91 /**********************************************************************/
92 /***** X Utility Functions *****/
93 /**********************************************************************/
97 * Return the host's byte order as LSBFirst or MSBFirst ala X.
99 static int host_byte_order( void )
102 char *cptr
= (char *) &i
;
103 return (*cptr
==1) ? LSBFirst
: MSBFirst
;
108 * Check if the X Shared Memory extension is available.
109 * Return: 0 = not available
110 * 1 = shared XImage support available
111 * 2 = shared Pixmap support available also
113 static int check_for_xshm( XMesaDisplay
*display
)
115 #if defined(USE_XSHM)
116 int major
, minor
, ignore
;
119 if (XQueryExtension( display
, "MIT-SHM", &ignore
, &ignore
, &ignore
)) {
120 if (XShmQueryVersion( display
, &major
, &minor
, &pixmaps
)==True
) {
121 return (pixmaps
==True
) ? 2 : 1;
131 /* No XSHM support */
138 * Apply gamma correction to an intensity value in [0..max]. Return the
139 * new intensity value.
142 gamma_adjust( GLfloat gamma
, GLint value
, GLint max
)
148 double x
= (double) value
/ (double) max
;
149 return IROUND_POS((GLfloat
) max
* pow(x
, 1.0F
/gamma
));
156 * Return the true number of bits per pixel for XImages.
157 * For example, if we request a 24-bit deep visual we may actually need/get
158 * 32bpp XImages. This function returns the appropriate bpp.
159 * Input: dpy - the X display
160 * visinfo - desribes the visual to be used for XImages
161 * Return: true number of bits per pixel for XImages
164 bits_per_pixel( XMesaVisual xmv
)
166 XMesaDisplay
*dpy
= xmv
->display
;
167 XMesaVisualInfo visinfo
= xmv
->visinfo
;
170 /* Create a temporary XImage */
171 img
= XCreateImage( dpy
, visinfo
->visual
, visinfo
->depth
,
172 ZPixmap
, 0, /*format, offset*/
173 (char*) MALLOC(8), /*data*/
174 1, 1, /*width, height*/
179 /* grab the bits/pixel value */
180 bitsPerPixel
= img
->bits_per_pixel
;
181 /* free the XImage */
184 XMesaDestroyImage( img
);
191 * Determine if a given X window ID is valid (window exists).
192 * Do this by calling XGetWindowAttributes() for the window and
193 * checking if we catch an X error.
194 * Input: dpy - the display
195 * win - the window to check for existance
196 * Return: GL_TRUE - window exists
197 * GL_FALSE - window doesn't exist
199 static GLboolean WindowExistsFlag
;
201 static int window_exists_err_handler( XMesaDisplay
* dpy
, XErrorEvent
* xerr
)
204 if (xerr
->error_code
== BadWindow
) {
205 WindowExistsFlag
= GL_FALSE
;
210 static GLboolean
window_exists( XMesaDisplay
*dpy
, Window win
)
212 XWindowAttributes wa
;
213 int (*old_handler
)( XMesaDisplay
*, XErrorEvent
* );
214 WindowExistsFlag
= GL_TRUE
;
215 old_handler
= XSetErrorHandler(window_exists_err_handler
);
216 XGetWindowAttributes( dpy
, win
, &wa
); /* dummy request */
217 XSetErrorHandler(old_handler
);
218 return WindowExistsFlag
;
222 get_drawable_size( XMesaDisplay
*dpy
, Drawable d
, GLuint
*width
, GLuint
*height
)
227 unsigned int w
, h
, bw
, depth
;
228 stat
= XGetGeometry(dpy
, d
, &root
, &xpos
, &ypos
, &w
, &h
, &bw
, &depth
);
236 * Return the size of the window (or pixmap) that corresponds to the
238 * \param width returns width in pixels
239 * \param height returns height in pixels
242 xmesa_get_window_size(XMesaDisplay
*dpy
, XMesaBuffer b
,
243 GLuint
*width
, GLuint
*height
)
247 _glthread_LOCK_MUTEX(_xmesa_lock
);
248 XSync(b
->xm_visual
->display
, 0); /* added for Chromium */
249 stat
= get_drawable_size(dpy
, b
->frontxrb
->pixmap
, width
, height
);
250 _glthread_UNLOCK_MUTEX(_xmesa_lock
);
253 /* probably querying a window that's recently been destroyed */
254 _mesa_warning(NULL
, "XGetGeometry failed!\n");
255 *width
= *height
= 1;
261 /**********************************************************************/
262 /***** Linked list of XMesaBuffers *****/
263 /**********************************************************************/
265 XMesaBuffer XMesaBufferList
= NULL
;
269 * Allocate a new XMesaBuffer object which corresponds to the given drawable.
270 * Note that XMesaBuffer is derived from struct gl_framebuffer.
271 * The new XMesaBuffer will not have any size (Width=Height=0).
273 * \param d the corresponding X drawable (window or pixmap)
274 * \param type either WINDOW, PIXMAP or PBUFFER, describing d
275 * \param vis the buffer's visual
276 * \param cmap the window's colormap, if known.
277 * \return new XMesaBuffer or NULL if any problem
280 create_xmesa_buffer(XMesaDrawable d
, BufferType type
,
281 XMesaVisual vis
, XMesaColormap cmap
)
285 ASSERT(type
== WINDOW
|| type
== PIXMAP
|| type
== PBUFFER
);
287 b
= (XMesaBuffer
) CALLOC_STRUCT(xmesa_buffer
);
291 b
->display
= vis
->display
;
296 _mesa_initialize_window_framebuffer(&b
->mesa_buffer
, &vis
->mesa_visual
);
297 b
->mesa_buffer
.Delete
= xmesa_delete_framebuffer
;
302 b
->frontxrb
= xmesa_new_renderbuffer(NULL
, 0, vis
, GL_FALSE
);
307 b
->frontxrb
->Parent
= b
;
308 b
->frontxrb
->drawable
= d
;
309 b
->frontxrb
->pixmap
= (XMesaPixmap
) d
;
310 _mesa_add_renderbuffer(&b
->mesa_buffer
, BUFFER_FRONT_LEFT
,
316 if (vis
->mesa_visual
.doubleBufferMode
) {
317 b
->backxrb
= xmesa_new_renderbuffer(NULL
, 0, vis
, GL_TRUE
);
319 /* XXX free front xrb too */
323 b
->backxrb
->Parent
= b
;
324 /* determine back buffer implementation */
325 b
->db_mode
= vis
->ximage_flag
? BACK_XIMAGE
: BACK_PIXMAP
;
327 _mesa_add_renderbuffer(&b
->mesa_buffer
, BUFFER_BACK_LEFT
,
332 * Other renderbuffer (depth, stencil, etc)
334 _mesa_add_soft_renderbuffers(&b
->mesa_buffer
,
335 GL_FALSE
, /* color */
336 vis
->mesa_visual
.haveDepthBuffer
,
337 vis
->mesa_visual
.haveStencilBuffer
,
338 vis
->mesa_visual
.haveAccumBuffer
,
339 GL_FALSE
, /* software alpha buffer */
340 vis
->mesa_visual
.numAuxBuffers
> 0 );
342 /* GLX_EXT_texture_from_pixmap */
343 b
->TextureTarget
= 0;
344 b
->TextureFormat
= GLX_TEXTURE_FORMAT_NONE_EXT
;
345 b
->TextureMipmap
= 0;
347 /* insert buffer into linked list */
348 b
->Next
= XMesaBufferList
;
356 * Find an XMesaBuffer by matching X display and colormap but NOT matching
357 * the notThis buffer.
360 xmesa_find_buffer(XMesaDisplay
*dpy
, XMesaColormap cmap
, XMesaBuffer notThis
)
363 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
364 if (b
->display
==dpy
&& b
->cmap
==cmap
&& b
!=notThis
) {
373 * Remove buffer from linked list, delete if no longer referenced.
376 xmesa_free_buffer(XMesaBuffer buffer
)
378 XMesaBuffer prev
= NULL
, b
;
380 for (b
= XMesaBufferList
; b
; b
= b
->Next
) {
382 struct gl_framebuffer
*fb
= &buffer
->mesa_buffer
;
384 /* unlink buffer from list */
386 prev
->Next
= buffer
->Next
;
388 XMesaBufferList
= buffer
->Next
;
390 /* mark as delete pending */
391 fb
->DeletePending
= GL_TRUE
;
393 /* Since the X window for the XMesaBuffer is going away, we don't
394 * want to dereference this pointer in the future.
396 b
->frontxrb
->drawable
= 0;
398 /* Unreference. If count = zero we'll really delete the buffer */
399 _mesa_reference_framebuffer(&fb
, NULL
);
403 /* continue search */
406 /* buffer not found in XMesaBufferList */
407 _mesa_problem(NULL
,"xmesa_free_buffer() - buffer not found\n");
413 /**********************************************************************/
414 /***** Misc Private Functions *****/
415 /**********************************************************************/
419 * Setup RGB rendering for a window with a True/DirectColor visual.
422 setup_truecolor(XMesaVisual v
, XMesaBuffer buffer
, XMesaColormap cmap
)
424 unsigned long rmask
, gmask
, bmask
;
428 /* Compute red multiplier (mask) and bit shift */
430 rmask
= GET_REDMASK(v
);
431 while ((rmask
& 1)==0) {
436 /* Compute green multiplier (mask) and bit shift */
438 gmask
= GET_GREENMASK(v
);
439 while ((gmask
& 1)==0) {
444 /* Compute blue multiplier (mask) and bit shift */
446 bmask
= GET_BLUEMASK(v
);
447 while ((bmask
& 1)==0) {
453 * Compute component-to-pixel lookup tables and dithering kernel
456 static GLubyte kernel
[16] = {
457 0*16, 8*16, 2*16, 10*16,
458 12*16, 4*16, 14*16, 6*16,
459 3*16, 11*16, 1*16, 9*16,
460 15*16, 7*16, 13*16, 5*16,
462 GLint rBits
= _mesa_bitcount(rmask
);
463 GLint gBits
= _mesa_bitcount(gmask
);
464 GLint bBits
= _mesa_bitcount(bmask
);
468 /* convert pixel components in [0,_mask] to RGB values in [0,255] */
469 for (i
=0; i
<=rmask
; i
++)
470 v
->PixelToR
[i
] = (unsigned char) ((i
* 255) / rmask
);
471 for (i
=0; i
<=gmask
; i
++)
472 v
->PixelToG
[i
] = (unsigned char) ((i
* 255) / gmask
);
473 for (i
=0; i
<=bmask
; i
++)
474 v
->PixelToB
[i
] = (unsigned char) ((i
* 255) / bmask
);
476 /* convert RGB values from [0,255] to pixel components */
478 for (i
=0;i
<256;i
++) {
479 GLint r
= gamma_adjust(v
->RedGamma
, i
, 255);
480 GLint g
= gamma_adjust(v
->GreenGamma
, i
, 255);
481 GLint b
= gamma_adjust(v
->BlueGamma
, i
, 255);
482 v
->RtoPixel
[i
] = (r
>> (8-rBits
)) << v
->rshift
;
483 v
->GtoPixel
[i
] = (g
>> (8-gBits
)) << v
->gshift
;
484 v
->BtoPixel
[i
] = (b
>> (8-bBits
)) << v
->bshift
;
486 /* overflow protection */
487 for (i
=256;i
<512;i
++) {
488 v
->RtoPixel
[i
] = v
->RtoPixel
[255];
489 v
->GtoPixel
[i
] = v
->GtoPixel
[255];
490 v
->BtoPixel
[i
] = v
->BtoPixel
[255];
493 /* setup dithering kernel */
495 if (gBits
> maxBits
) maxBits
= gBits
;
496 if (bBits
> maxBits
) maxBits
= bBits
;
498 v
->Kernel
[i
] = kernel
[i
] >> maxBits
;
501 v
->undithered_pf
= PF_Truecolor
;
502 v
->dithered_pf
= (GET_VISUAL_DEPTH(v
)<24) ? PF_Dither_True
: PF_Truecolor
;
506 * Now check for TrueColor visuals which we can optimize.
508 if ( GET_REDMASK(v
) ==0x0000ff
509 && GET_GREENMASK(v
)==0x00ff00
510 && GET_BLUEMASK(v
) ==0xff0000
511 && CHECK_BYTE_ORDER(v
)
512 && v
->BitsPerPixel
==32
513 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
514 /* common 32 bpp config used on SGI, Sun */
515 v
->undithered_pf
= v
->dithered_pf
= PF_8A8B8G8R
; /* ABGR */
517 else if (GET_REDMASK(v
) == 0xff0000
518 && GET_GREENMASK(v
)== 0x00ff00
519 && GET_BLUEMASK(v
) == 0x0000ff
520 && CHECK_BYTE_ORDER(v
)
521 && v
->RedGamma
== 1.0 && v
->GreenGamma
== 1.0 && v
->BlueGamma
== 1.0){
522 if (v
->BitsPerPixel
==32) {
523 /* if 32 bpp, and visual indicates 8 bpp alpha channel */
524 if (GET_VISUAL_DEPTH(v
) == 32 && v
->mesa_visual
.alphaBits
== 8)
525 v
->undithered_pf
= v
->dithered_pf
= PF_8A8R8G8B
; /* ARGB */
527 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B
; /* xRGB */
529 else if (v
->BitsPerPixel
== 24) {
530 v
->undithered_pf
= v
->dithered_pf
= PF_8R8G8B24
; /* RGB */
533 else if (GET_REDMASK(v
) ==0xf800
534 && GET_GREENMASK(v
)==0x07e0
535 && GET_BLUEMASK(v
) ==0x001f
536 && CHECK_BYTE_ORDER(v
)
537 && v
->BitsPerPixel
==16
538 && v
->RedGamma
==1.0 && v
->GreenGamma
==1.0 && v
->BlueGamma
==1.0) {
540 v
->undithered_pf
= PF_5R6G5B
;
541 v
->dithered_pf
= PF_Dither_5R6G5B
;
547 * When a context is bound for the first time, we can finally finish
548 * initializing the context's visual and buffer information.
549 * \param v the XMesaVisual to initialize
550 * \param b the XMesaBuffer to initialize (may be NULL)
551 * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode
552 * \param window the window/pixmap we're rendering into
553 * \param cmap the colormap associated with the window/pixmap
554 * \return GL_TRUE=success, GL_FALSE=failure
557 initialize_visual_and_buffer(XMesaVisual v
, XMesaBuffer b
,
558 XMesaDrawable window
,
561 const int xclass
= v
->visualType
;
564 ASSERT(!b
|| b
->xm_visual
== v
);
566 /* Save true bits/pixel */
567 v
->BitsPerPixel
= bits_per_pixel(v
);
568 assert(v
->BitsPerPixel
> 0);
571 * We support RGB rendering into almost any kind of visual.
573 if (xclass
== GLX_TRUE_COLOR
|| xclass
== GLX_DIRECT_COLOR
) {
574 setup_truecolor( v
, b
, cmap
);
577 _mesa_warning(NULL
, "XMesa: RGB mode rendering not supported in given visual.\n");
580 v
->mesa_visual
.indexBits
= 0;
582 if (_mesa_getenv("MESA_NO_DITHER")) {
583 v
->dithered_pf
= v
->undithered_pf
;
588 * If MESA_INFO env var is set print out some debugging info
589 * which can help Brian figure out what's going on when a user
592 if (_mesa_getenv("MESA_INFO")) {
593 printf("X/Mesa visual = %p\n", (void *) v
);
594 printf("X/Mesa dithered pf = %u\n", v
->dithered_pf
);
595 printf("X/Mesa undithered pf = %u\n", v
->undithered_pf
);
596 printf("X/Mesa level = %d\n", v
->mesa_visual
.level
);
597 printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v
));
598 printf("X/Mesa bits per pixel = %d\n", v
->BitsPerPixel
);
604 /* Do window-specific initializations */
606 /* these should have been set in create_xmesa_buffer */
607 ASSERT(b
->frontxrb
->drawable
== window
);
608 ASSERT(b
->frontxrb
->pixmap
== (XMesaPixmap
) window
);
610 /* Setup for single/double buffering */
611 if (v
->mesa_visual
.doubleBufferMode
) {
612 /* Double buffered */
613 b
->shm
= check_for_xshm( v
->display
);
616 /* X11 graphics contexts */
617 b
->gc
= XCreateGC( v
->display
, window
, 0, NULL
);
618 XMesaSetFunction( v
->display
, b
->gc
, GXcopy
);
620 /* cleargc - for glClear() */
621 b
->cleargc
= XCreateGC( v
->display
, window
, 0, NULL
);
622 XMesaSetFunction( v
->display
, b
->cleargc
, GXcopy
);
625 * Don't generate Graphics Expose/NoExpose events in swapbuffers().
626 * Patch contributed by Michael Pichler May 15, 1995.
630 gcvalues
.graphics_exposures
= False
;
631 b
->swapgc
= XCreateGC(v
->display
, window
,
632 GCGraphicsExposures
, &gcvalues
);
634 XMesaSetFunction( v
->display
, b
->swapgc
, GXcopy
);
636 /* Initialize the row buffer XImage for use in write_color_span() */
637 data
= (char*) MALLOC(MAX_WIDTH
*4);
638 b
->rowimage
= XCreateImage( v
->display
,
641 ZPixmap
, 0, /*format, offset*/
643 MAX_WIDTH
, 1, /*width, height*/
645 0 /*bytes_per_line*/ );
656 * Convert an RGBA color to a pixel value.
659 xmesa_color_to_pixel(struct gl_context
*ctx
,
660 GLubyte r
, GLubyte g
, GLubyte b
, GLubyte a
,
663 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
664 switch (pixelFormat
) {
668 PACK_TRUECOLOR( p
, r
, g
, b
);
672 return PACK_8A8B8G8R( r
, g
, b
, a
);
674 return PACK_8A8R8G8B( r
, g
, b
, a
);
678 return PACK_8R8G8B( r
, g
, b
);
680 return PACK_5R6G5B( r
, g
, b
);
683 case PF_Dither_5R6G5B
:
686 PACK_TRUEDITHER(p
, 1, 0, r
, g
, b
);
690 _mesa_problem(ctx
, "Bad pixel format in xmesa_color_to_pixel");
696 #define NUM_VISUAL_TYPES 6
699 * Convert an X visual type to a GLX visual type.
701 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
703 * \return If \c visualType is a valid X visual type, a GLX visual type will
704 * be returned. Otherwise \c GLX_NONE will be returned.
707 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
711 xmesa_convert_from_x_visual_type( int visualType
)
713 static const int glx_visual_types
[ NUM_VISUAL_TYPES
] = {
714 GLX_STATIC_GRAY
, GLX_GRAY_SCALE
,
715 GLX_STATIC_COLOR
, GLX_PSEUDO_COLOR
,
716 GLX_TRUE_COLOR
, GLX_DIRECT_COLOR
719 return ( (unsigned) visualType
< NUM_VISUAL_TYPES
)
720 ? glx_visual_types
[ visualType
] : GLX_NONE
;
724 /**********************************************************************/
725 /***** Public Functions *****/
726 /**********************************************************************/
730 * Create a new X/Mesa visual.
731 * Input: display - X11 display
732 * visinfo - an XVisualInfo pointer
733 * rgb_flag - GL_TRUE = RGB mode,
734 * GL_FALSE = color index mode
735 * alpha_flag - alpha buffer requested?
736 * db_flag - GL_TRUE = double-buffered,
737 * GL_FALSE = single buffered
738 * stereo_flag - stereo visual?
739 * ximage_flag - GL_TRUE = use an XImage for back buffer,
740 * GL_FALSE = use an off-screen pixmap for back buffer
741 * depth_size - requested bits/depth values, or zero
742 * stencil_size - requested bits/stencil values, or zero
743 * accum_red_size - requested bits/red accum values, or zero
744 * accum_green_size - requested bits/green accum values, or zero
745 * accum_blue_size - requested bits/blue accum values, or zero
746 * accum_alpha_size - requested bits/alpha accum values, or zero
747 * num_samples - number of samples/pixel if multisampling, or zero
748 * level - visual level, usually 0
749 * visualCaveat - ala the GLX extension, usually GLX_NONE
750 * Return; a new XMesaVisual or 0 if error.
753 XMesaVisual
XMesaCreateVisual( XMesaDisplay
*display
,
754 XMesaVisualInfo visinfo
,
756 GLboolean alpha_flag
,
758 GLboolean stereo_flag
,
759 GLboolean ximage_flag
,
762 GLint accum_red_size
,
763 GLint accum_green_size
,
764 GLint accum_blue_size
,
765 GLint accum_alpha_size
,
772 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
774 /* For debugging only */
775 if (_mesa_getenv("MESA_XSYNC")) {
776 /* This makes debugging X easier.
777 * In your debugger, set a breakpoint on _XError to stop when an
778 * X protocol error is generated.
780 XSynchronize( display
, 1 );
783 /* Color-index rendering not supported. */
787 v
= (XMesaVisual
) CALLOC_STRUCT(xmesa_visual
);
792 v
->display
= display
;
794 /* Save a copy of the XVisualInfo struct because the user may Xfree()
795 * the struct but we may need some of the information contained in it
798 v
->visinfo
= (XVisualInfo
*) MALLOC(sizeof(*visinfo
));
803 memcpy(v
->visinfo
, visinfo
, sizeof(*visinfo
));
805 /* check for MESA_GAMMA environment variable */
806 gamma
= _mesa_getenv("MESA_GAMMA");
808 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 0.0;
809 sscanf( gamma
, "%f %f %f", &v
->RedGamma
, &v
->GreenGamma
, &v
->BlueGamma
);
810 if (v
->RedGamma
<=0.0) v
->RedGamma
= 1.0;
811 if (v
->GreenGamma
<=0.0) v
->GreenGamma
= v
->RedGamma
;
812 if (v
->BlueGamma
<=0.0) v
->BlueGamma
= v
->RedGamma
;
815 v
->RedGamma
= v
->GreenGamma
= v
->BlueGamma
= 1.0;
818 v
->ximage_flag
= ximage_flag
;
820 v
->mesa_visual
.redMask
= visinfo
->red_mask
;
821 v
->mesa_visual
.greenMask
= visinfo
->green_mask
;
822 v
->mesa_visual
.blueMask
= visinfo
->blue_mask
;
823 v
->visualID
= visinfo
->visualid
;
824 v
->screen
= visinfo
->screen
;
826 #if !(defined(__cplusplus) || defined(c_plusplus))
827 v
->visualType
= xmesa_convert_from_x_visual_type(visinfo
->class);
829 v
->visualType
= xmesa_convert_from_x_visual_type(visinfo
->c_class
);
832 v
->mesa_visual
.visualRating
= visualCaveat
;
835 v
->mesa_visual
.alphaBits
= 8;
837 (void) initialize_visual_and_buffer( v
, NULL
, 0, 0 );
840 const int xclass
= v
->visualType
;
841 if (xclass
== GLX_TRUE_COLOR
|| xclass
== GLX_DIRECT_COLOR
) {
842 red_bits
= _mesa_bitcount(GET_REDMASK(v
));
843 green_bits
= _mesa_bitcount(GET_GREENMASK(v
));
844 blue_bits
= _mesa_bitcount(GET_BLUEMASK(v
));
847 /* this is an approximation */
849 depth
= GET_VISUAL_DEPTH(v
);
850 red_bits
= depth
/ 3;
852 green_bits
= depth
/ 2;
856 assert( red_bits
+ green_bits
+ blue_bits
== GET_VISUAL_DEPTH(v
) );
858 alpha_bits
= v
->mesa_visual
.alphaBits
;
861 _mesa_initialize_visual( &v
->mesa_visual
,
862 db_flag
, stereo_flag
,
863 red_bits
, green_bits
,
864 blue_bits
, alpha_bits
,
867 accum_red_size
, accum_green_size
,
868 accum_blue_size
, accum_alpha_size
,
872 v
->mesa_visual
.level
= level
;
878 void XMesaDestroyVisual( XMesaVisual v
)
887 * Create a new XMesaContext.
888 * \param v the XMesaVisual
889 * \param share_list another XMesaContext with which to share display
890 * lists or NULL if no sharing is wanted.
891 * \return an XMesaContext or NULL if error.
894 XMesaContext
XMesaCreateContext( XMesaVisual v
, XMesaContext share_list
)
896 static GLboolean firstTime
= GL_TRUE
;
898 struct gl_context
*mesaCtx
;
899 struct dd_function_table functions
;
903 _glthread_INIT_MUTEX(_xmesa_lock
);
904 firstTime
= GL_FALSE
;
907 /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */
908 c
= (XMesaContext
) CALLOC_STRUCT(xmesa_context
);
912 mesaCtx
= &(c
->mesa
);
914 /* initialize with default driver functions, then plug in XMesa funcs */
915 _mesa_init_driver_functions(&functions
);
916 xmesa_init_driver_functions(v
, &functions
);
917 if (!_mesa_initialize_context(mesaCtx
, API_OPENGL
, &v
->mesa_visual
,
918 share_list
? &(share_list
->mesa
) : (struct gl_context
*) NULL
,
919 &functions
, (void *) c
)) {
924 /* Enable this to exercise fixed function -> shader translation
925 * with software rendering.
928 mesaCtx
->VertexProgram
._MaintainTnlProgram
= GL_TRUE
;
929 mesaCtx
->FragmentProgram
._MaintainTexEnvProgram
= GL_TRUE
;
932 _mesa_enable_sw_extensions(mesaCtx
);
933 _mesa_enable_1_3_extensions(mesaCtx
);
934 _mesa_enable_1_4_extensions(mesaCtx
);
935 _mesa_enable_1_5_extensions(mesaCtx
);
936 _mesa_enable_2_0_extensions(mesaCtx
);
937 _mesa_enable_2_1_extensions(mesaCtx
);
938 #if ENABLE_EXT_texure_compression_s3tc
939 if (mesaCtx
->Mesa_DXTn
) {
940 _mesa_enable_extension(mesaCtx
, "GL_EXT_texture_compression_s3tc");
941 _mesa_enable_extension(mesaCtx
, "GL_S3_s3tc");
943 _mesa_enable_extension(mesaCtx
, "GL_3DFX_texture_compression_FXT1");
945 #if ENABLE_EXT_timer_query
946 _mesa_enable_extension(mesaCtx
, "GL_EXT_timer_query");
950 /* finish up xmesa context initializations */
951 c
->swapbytes
= CHECK_BYTE_ORDER(v
) ? GL_FALSE
: GL_TRUE
;
953 c
->xm_buffer
= NULL
; /* set later by XMesaMakeCurrent */
954 c
->display
= v
->display
;
955 c
->pixelformat
= v
->dithered_pf
; /* Dithering is enabled by default */
957 /* Initialize the software rasterizer and helper modules.
959 if (!_swrast_CreateContext( mesaCtx
) ||
960 !_vbo_CreateContext( mesaCtx
) ||
961 !_tnl_CreateContext( mesaCtx
) ||
962 !_swsetup_CreateContext( mesaCtx
)) {
963 _mesa_free_context_data(&c
->mesa
);
969 tnl
= TNL_CONTEXT(mesaCtx
);
970 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
972 xmesa_register_swrast_functions( mesaCtx
);
973 _swsetup_Wakeup(mesaCtx
);
975 _mesa_meta_init(mesaCtx
);
983 void XMesaDestroyContext( XMesaContext c
)
985 struct gl_context
*mesaCtx
= &c
->mesa
;
987 _mesa_meta_free( mesaCtx
);
989 _swsetup_DestroyContext( mesaCtx
);
990 _swrast_DestroyContext( mesaCtx
);
991 _tnl_DestroyContext( mesaCtx
);
992 _vbo_DestroyContext( mesaCtx
);
993 _mesa_free_context_data( mesaCtx
);
1000 * Private function for creating an XMesaBuffer which corresponds to an
1001 * X window or pixmap.
1002 * \param v the window's XMesaVisual
1003 * \param w the window we're wrapping
1004 * \return new XMesaBuffer or NULL if error
1007 XMesaCreateWindowBuffer(XMesaVisual v
, XMesaWindow w
)
1009 XWindowAttributes attr
;
1017 /* Check that window depth matches visual depth */
1018 XGetWindowAttributes( v
->display
, w
, &attr
);
1020 if (GET_VISUAL_DEPTH(v
) != depth
) {
1021 _mesa_warning(NULL
, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1022 GET_VISUAL_DEPTH(v
), depth
);
1027 if (attr
.colormap
) {
1028 cmap
= attr
.colormap
;
1031 _mesa_warning(NULL
, "Window %u has no colormap!\n", (unsigned int) w
);
1032 /* this is weird, a window w/out a colormap!? */
1033 /* OK, let's just allocate a new one and hope for the best */
1034 cmap
= XCreateColormap(v
->display
, w
, attr
.visual
, AllocNone
);
1037 b
= create_xmesa_buffer((XMesaDrawable
) w
, WINDOW
, v
, cmap
);
1041 if (!initialize_visual_and_buffer( v
, b
, (XMesaDrawable
) w
, cmap
)) {
1042 xmesa_free_buffer(b
);
1052 * Create a new XMesaBuffer from an X pixmap.
1054 * \param v the XMesaVisual
1055 * \param p the pixmap
1056 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1057 * \c GLX_DIRECT_COLOR visual for the pixmap
1058 * \returns new XMesaBuffer or NULL if error
1061 XMesaCreatePixmapBuffer(XMesaVisual v
, XMesaPixmap p
, XMesaColormap cmap
)
1067 b
= create_xmesa_buffer((XMesaDrawable
) p
, PIXMAP
, v
, cmap
);
1071 if (!initialize_visual_and_buffer(v
, b
, (XMesaDrawable
) p
, cmap
)) {
1072 xmesa_free_buffer(b
);
1081 * For GLX_EXT_texture_from_pixmap
1084 XMesaCreatePixmapTextureBuffer(XMesaVisual v
, XMesaPixmap p
,
1086 int format
, int target
, int mipmap
)
1088 GET_CURRENT_CONTEXT(ctx
);
1090 GLuint width
, height
;
1094 b
= create_xmesa_buffer((XMesaDrawable
) p
, PIXMAP
, v
, cmap
);
1098 /* get pixmap size, update framebuffer/renderbuffer dims */
1099 xmesa_get_window_size(v
->display
, b
, &width
, &height
);
1100 _mesa_resize_framebuffer(NULL
, &(b
->mesa_buffer
), width
, height
);
1104 if (ctx
->Extensions
.ARB_texture_non_power_of_two
) {
1105 target
= GLX_TEXTURE_2D_EXT
;
1107 else if ( _mesa_bitcount(width
) == 1
1108 && _mesa_bitcount(height
) == 1) {
1109 /* power of two size */
1111 target
= GLX_TEXTURE_1D_EXT
;
1114 target
= GLX_TEXTURE_2D_EXT
;
1117 else if (ctx
->Extensions
.NV_texture_rectangle
) {
1118 target
= GLX_TEXTURE_RECTANGLE_EXT
;
1121 /* non power of two textures not supported */
1122 XMesaDestroyBuffer(b
);
1127 b
->TextureTarget
= target
;
1128 b
->TextureFormat
= format
;
1129 b
->TextureMipmap
= mipmap
;
1131 if (!initialize_visual_and_buffer(v
, b
, (XMesaDrawable
) p
, cmap
)) {
1132 xmesa_free_buffer(b
);
1142 XMesaCreatePBuffer(XMesaVisual v
, XMesaColormap cmap
,
1143 unsigned int width
, unsigned int height
)
1146 XMesaDrawable drawable
; /* X Pixmap Drawable */
1149 /* allocate pixmap for front buffer */
1150 root
= RootWindow( v
->display
, v
->visinfo
->screen
);
1151 drawable
= XCreatePixmap(v
->display
, root
, width
, height
,
1156 b
= create_xmesa_buffer(drawable
, PBUFFER
, v
, cmap
);
1160 if (!initialize_visual_and_buffer(v
, b
, drawable
, cmap
)) {
1161 xmesa_free_buffer(b
);
1171 * Deallocate an XMesaBuffer structure and all related info.
1174 XMesaDestroyBuffer(XMesaBuffer b
)
1176 xmesa_free_buffer(b
);
1181 * Query the current window size and update the corresponding struct gl_framebuffer
1182 * and all attached renderbuffers.
1184 * 1. the first time a buffer is bound to a context.
1185 * 2. from glViewport to poll for window size changes
1186 * 3. from the XMesaResizeBuffers() API function.
1187 * Note: it's possible (and legal) for xmctx to be NULL. That can happen
1188 * when resizing a buffer when no rendering context is bound.
1191 xmesa_check_and_update_buffer_size(XMesaContext xmctx
, XMesaBuffer drawBuffer
)
1193 GLuint width
, height
;
1194 xmesa_get_window_size(drawBuffer
->display
, drawBuffer
, &width
, &height
);
1195 if (drawBuffer
->mesa_buffer
.Width
!= width
||
1196 drawBuffer
->mesa_buffer
.Height
!= height
) {
1197 struct gl_context
*ctx
= xmctx
? &xmctx
->mesa
: NULL
;
1198 _mesa_resize_framebuffer(ctx
, &(drawBuffer
->mesa_buffer
), width
, height
);
1200 drawBuffer
->mesa_buffer
.Initialized
= GL_TRUE
; /* XXX TEMPORARY? */
1205 * Bind buffer b to context c and make c the current rendering context.
1207 GLboolean
XMesaMakeCurrent( XMesaContext c
, XMesaBuffer b
)
1209 return XMesaMakeCurrent2( c
, b
, b
);
1214 * Bind buffer b to context c and make c the current rendering context.
1217 GLboolean
XMesaMakeCurrent2( XMesaContext c
, XMesaBuffer drawBuffer
,
1218 XMesaBuffer readBuffer
)
1221 if (!drawBuffer
|| !readBuffer
)
1222 return GL_FALSE
; /* must specify buffers! */
1224 if (&(c
->mesa
) == _mesa_get_current_context()
1225 && c
->mesa
.DrawBuffer
== &drawBuffer
->mesa_buffer
1226 && c
->mesa
.ReadBuffer
== &readBuffer
->mesa_buffer
1227 && XMESA_BUFFER(c
->mesa
.DrawBuffer
)->wasCurrent
) {
1228 /* same context and buffer, do nothing */
1232 c
->xm_buffer
= drawBuffer
;
1234 /* Call this periodically to detect when the user has begun using
1235 * GL rendering from multiple threads.
1237 _glapi_check_multithread();
1239 xmesa_check_and_update_buffer_size(c
, drawBuffer
);
1240 if (readBuffer
!= drawBuffer
)
1241 xmesa_check_and_update_buffer_size(c
, readBuffer
);
1243 _mesa_make_current(&(c
->mesa
),
1244 &drawBuffer
->mesa_buffer
,
1245 &readBuffer
->mesa_buffer
);
1248 * Must recompute and set these pixel values because colormap
1249 * can be different for different windows.
1251 c
->clearpixel
= xmesa_color_to_pixel( &c
->mesa
,
1256 c
->xm_visual
->undithered_pf
);
1257 XMesaSetForeground(c
->display
, drawBuffer
->cleargc
, c
->clearpixel
);
1259 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1260 drawBuffer
->wasCurrent
= GL_TRUE
;
1264 _mesa_make_current( NULL
, NULL
, NULL
);
1271 * Unbind the context c from its buffer.
1273 GLboolean
XMesaUnbindContext( XMesaContext c
)
1275 /* A no-op for XFree86 integration purposes */
1280 XMesaContext
XMesaGetCurrentContext( void )
1282 GET_CURRENT_CONTEXT(ctx
);
1284 XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
1293 XMesaBuffer
XMesaGetCurrentBuffer( void )
1295 GET_CURRENT_CONTEXT(ctx
);
1297 XMesaBuffer xmbuf
= XMESA_BUFFER(ctx
->DrawBuffer
);
1306 /* New in Mesa 3.1 */
1307 XMesaBuffer
XMesaGetCurrentReadBuffer( void )
1309 GET_CURRENT_CONTEXT(ctx
);
1311 return XMESA_BUFFER(ctx
->ReadBuffer
);
1320 GLboolean
XMesaSetFXmode( GLint mode
)
1329 * Copy the back buffer to the front buffer. If there's no back buffer
1333 void XMesaSwapBuffers( XMesaBuffer b
)
1335 GET_CURRENT_CONTEXT(ctx
);
1338 /* single buffered */
1342 /* If we're swapping the buffer associated with the current context
1343 * we have to flush any pending rendering commands first.
1345 if (ctx
&& ctx
->DrawBuffer
== &(b
->mesa_buffer
))
1346 _mesa_notifySwapBuffers(ctx
);
1349 if (b
->backxrb
->ximage
) {
1350 /* Copy Ximage (back buf) from client memory to server window */
1351 #if defined(USE_XSHM)
1353 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
1354 XShmPutImage( b
->xm_visual
->display
, b
->frontxrb
->drawable
,
1356 b
->backxrb
->ximage
, 0, 0,
1357 0, 0, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
,
1359 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
1364 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
1365 XMesaPutImage( b
->xm_visual
->display
, b
->frontxrb
->drawable
,
1367 b
->backxrb
->ximage
, 0, 0,
1368 0, 0, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
);
1369 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
1372 else if (b
->backxrb
->pixmap
) {
1373 /* Copy pixmap (back buf) to window (front buf) on server */
1374 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
1375 XMesaCopyArea( b
->xm_visual
->display
,
1376 b
->backxrb
->pixmap
, /* source drawable */
1377 b
->frontxrb
->drawable
, /* dest. drawable */
1379 0, 0, b
->mesa_buffer
.Width
, b
->mesa_buffer
.Height
,
1380 0, 0 /* dest region */
1382 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
1385 XSync( b
->xm_visual
->display
, False
);
1391 * Copy sub-region of back buffer to front buffer
1393 void XMesaCopySubBuffer( XMesaBuffer b
, int x
, int y
, int width
, int height
)
1395 GET_CURRENT_CONTEXT(ctx
);
1397 /* If we're swapping the buffer associated with the current context
1398 * we have to flush any pending rendering commands first.
1400 if (ctx
&& ctx
->DrawBuffer
== &(b
->mesa_buffer
))
1401 _mesa_notifySwapBuffers(ctx
);
1404 /* single buffered */
1409 int yTop
= b
->mesa_buffer
.Height
- y
- height
;
1410 if (b
->backxrb
->ximage
) {
1411 /* Copy Ximage from host's memory to server's window */
1412 #if defined(USE_XSHM)
1414 /* XXX assuming width and height aren't too large! */
1415 XShmPutImage( b
->xm_visual
->display
, b
->frontxrb
->drawable
,
1417 b
->backxrb
->ximage
, x
, yTop
,
1418 x
, yTop
, width
, height
, False
);
1419 /* wait for finished event??? */
1424 /* XXX assuming width and height aren't too large! */
1425 XMesaPutImage( b
->xm_visual
->display
, b
->frontxrb
->drawable
,
1427 b
->backxrb
->ximage
, x
, yTop
,
1428 x
, yTop
, width
, height
);
1432 /* Copy pixmap to window on server */
1433 XMesaCopyArea( b
->xm_visual
->display
,
1434 b
->backxrb
->pixmap
, /* source drawable */
1435 b
->frontxrb
->drawable
, /* dest. drawable */
1437 x
, yTop
, width
, height
, /* source region */
1438 x
, yTop
/* dest region */
1446 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
1447 * is a way to get "under the hood" of X/Mesa so one can manipulate the
1448 * back buffer directly.
1449 * Output: pixmap - pointer to back buffer's Pixmap, or 0
1450 * ximage - pointer to back buffer's XImage, or NULL
1451 * Return: GL_TRUE = context is double buffered
1452 * GL_FALSE = context is single buffered
1454 GLboolean
XMesaGetBackBuffer( XMesaBuffer b
,
1455 XMesaPixmap
*pixmap
,
1456 XMesaImage
**ximage
)
1460 *pixmap
= b
->backxrb
->pixmap
;
1462 *ximage
= b
->backxrb
->ximage
;
1474 * Return the depth buffer associated with an XMesaBuffer.
1475 * Input: b - the XMesa buffer handle
1476 * Output: width, height - size of buffer in pixels
1477 * bytesPerValue - bytes per depth value (2 or 4)
1478 * buffer - pointer to depth buffer values
1479 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1481 GLboolean
XMesaGetDepthBuffer( XMesaBuffer b
, GLint
*width
, GLint
*height
,
1482 GLint
*bytesPerValue
, void **buffer
)
1484 struct gl_renderbuffer
*rb
1485 = b
->mesa_buffer
.Attachment
[BUFFER_DEPTH
].Renderbuffer
;
1486 if (!rb
|| !rb
->Data
) {
1494 *width
= b
->mesa_buffer
.Width
;
1495 *height
= b
->mesa_buffer
.Height
;
1496 *bytesPerValue
= b
->mesa_buffer
.Visual
.depthBits
<= 16
1497 ? sizeof(GLushort
) : sizeof(GLuint
);
1504 void XMesaFlush( XMesaContext c
)
1506 if (c
&& c
->xm_visual
) {
1507 XSync( c
->xm_visual
->display
, False
);
1513 const char *XMesaGetString( XMesaContext c
, int name
)
1516 if (name
==XMESA_VERSION
) {
1519 else if (name
==XMESA_EXTENSIONS
) {
1529 XMesaBuffer
XMesaFindBuffer( XMesaDisplay
*dpy
, XMesaDrawable d
)
1532 for (b
=XMesaBufferList
; b
; b
=b
->Next
) {
1533 if (b
->frontxrb
->drawable
== d
&& b
->display
== dpy
) {
1542 * Free/destroy all XMesaBuffers associated with given display.
1544 void xmesa_destroy_buffers_on_display(XMesaDisplay
*dpy
)
1546 XMesaBuffer b
, next
;
1547 for (b
= XMesaBufferList
; b
; b
= next
) {
1549 if (b
->display
== dpy
) {
1550 xmesa_free_buffer(b
);
1557 * Look for XMesaBuffers whose X window has been destroyed.
1558 * Deallocate any such XMesaBuffers.
1560 void XMesaGarbageCollect( XMesaDisplay
* dpy
)
1562 XMesaBuffer b
, next
;
1563 for (b
=XMesaBufferList
; b
; b
=next
) {
1565 if (b
->display
&& b
->display
== dpy
&& b
->frontxrb
->drawable
&& b
->type
== WINDOW
) {
1566 XSync(b
->display
, False
);
1567 if (!window_exists( b
->display
, b
->frontxrb
->drawable
)) {
1568 /* found a dead window, free the ancillary info */
1569 XMesaDestroyBuffer( b
);
1576 unsigned long XMesaDitherColor( XMesaContext xmesa
, GLint x
, GLint y
,
1577 GLfloat red
, GLfloat green
,
1578 GLfloat blue
, GLfloat alpha
)
1580 GLint r
= (GLint
) (red
* 255.0F
);
1581 GLint g
= (GLint
) (green
* 255.0F
);
1582 GLint b
= (GLint
) (blue
* 255.0F
);
1583 GLint a
= (GLint
) (alpha
* 255.0F
);
1585 switch (xmesa
->pixelformat
) {
1589 PACK_TRUECOLOR( p
, r
, g
, b
);
1593 return PACK_8A8B8G8R( r
, g
, b
, a
);
1595 return PACK_8A8R8G8B( r
, g
, b
, a
);
1597 return PACK_8R8G8B( r
, g
, b
);
1599 return PACK_5R6G5B( r
, g
, b
);
1600 case PF_Dither_5R6G5B
:
1602 case PF_Dither_True
:
1605 PACK_TRUEDITHER(p
, x
, y
, r
, g
, b
);
1609 _mesa_problem(NULL
, "Bad pixel format in XMesaDitherColor");
1616 * This is typically called when the window size changes and we need
1617 * to reallocate the buffer's back/depth/stencil/accum buffers.
1620 XMesaResizeBuffers( XMesaBuffer b
)
1622 GET_CURRENT_CONTEXT(ctx
);
1623 XMesaContext xmctx
= XMESA_CONTEXT(ctx
);
1626 xmesa_check_and_update_buffer_size(xmctx
, b
);
1631 xbuffer_to_renderbuffer(int buffer
)
1633 assert(MAX_AUX_BUFFERS
<= 4);
1636 case GLX_FRONT_LEFT_EXT
:
1637 return BUFFER_FRONT_LEFT
;
1638 case GLX_FRONT_RIGHT_EXT
:
1639 return BUFFER_FRONT_RIGHT
;
1640 case GLX_BACK_LEFT_EXT
:
1641 return BUFFER_BACK_LEFT
;
1642 case GLX_BACK_RIGHT_EXT
:
1643 return BUFFER_BACK_RIGHT
;
1656 /* BadValue error */
1663 XMesaBindTexImage(XMesaDisplay
*dpy
, XMesaBuffer drawable
, int buffer
,
1664 const int *attrib_list
)
1667 GET_CURRENT_CONTEXT(ctx
);
1668 const GLuint unit
= ctx
->Texture
.CurrentUnit
;
1669 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1670 struct gl_texture_object
*texObj
;
1672 struct gl_renderbuffer
*rb
;
1673 struct xmesa_renderbuffer
*xrb
;
1675 XMesaImage
*img
= NULL
;
1676 GLboolean freeImg
= GL_FALSE
;
1678 b
= xbuffer_to_renderbuffer(buffer
);
1682 if (drawable
->TextureFormat
== GLX_TEXTURE_FORMAT_NONE_EXT
)
1683 return; /* BadMatch error */
1685 rb
= drawable
->mesa_buffer
.Attachment
[b
].Renderbuffer
;
1687 /* invalid buffer */
1690 xrb
= xmesa_renderbuffer(rb
);
1693 switch (drawable
->TextureTarget
) {
1694 case GLX_TEXTURE_1D_EXT
:
1695 texObj
= texUnit
->CurrentTex
[TEXTURE_1D_INDEX
];
1697 case GLX_TEXTURE_2D_EXT
:
1698 texObj
= texUnit
->CurrentTex
[TEXTURE_2D_INDEX
];
1700 case GLX_TEXTURE_RECTANGLE_EXT
:
1701 texObj
= texUnit
->CurrentTex
[TEXTURE_RECT_INDEX
];
1704 return; /* BadMatch error */
1709 * The following is a quick and simple way to implement
1710 * BindTexImage. The better way is to write some new FetchTexel()
1711 * functions which would extract texels from XImages. We'd still
1712 * need to use GetImage when texturing from a Pixmap (front buffer)
1713 * but texturing from a back buffer (XImage) would avoid an image
1719 img
= XMesaGetImage(dpy
, xrb
->pixmap
, 0, 0, rb
->Width
, rb
->Height
, ~0L,
1723 else if (xrb
->ximage
) {
1727 /* store the XImage as a new texture image */
1729 GLenum format
, type
, intFormat
;
1730 if (img
->bits_per_pixel
== 32) {
1732 type
= GL_UNSIGNED_BYTE
;
1733 intFormat
= GL_RGBA
;
1735 else if (img
->bits_per_pixel
== 24) {
1737 type
= GL_UNSIGNED_BYTE
;
1740 else if (img
->bits_per_pixel
== 16) {
1742 type
= GL_UNSIGNED_SHORT_5_6_5
;
1746 _mesa_problem(NULL
, "Unexpected XImage format in XMesaBindTexImage");
1749 if (drawable
->TextureFormat
== GLX_TEXTURE_FORMAT_RGBA_EXT
) {
1750 intFormat
= GL_RGBA
;
1752 else if (drawable
->TextureFormat
== GLX_TEXTURE_FORMAT_RGB_EXT
) {
1756 _mesa_TexImage2D(GL_TEXTURE_2D
, 0, intFormat
, rb
->Width
, rb
->Height
, 0,
1757 format
, type
, img
->data
);
1760 XMesaDestroyImage(img
);
1768 XMesaReleaseTexImage(XMesaDisplay
*dpy
, XMesaBuffer drawable
, int buffer
)
1770 const GLint b
= xbuffer_to_renderbuffer(buffer
);