1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg/** 26848b8605Smrg * \file xm_api.c 27848b8605Smrg * 28848b8605Smrg * All the XMesa* API functions. 29848b8605Smrg * 30848b8605Smrg * 31848b8605Smrg * NOTES: 32848b8605Smrg * 33848b8605Smrg * The window coordinate system origin (0,0) is in the lower-left corner 34848b8605Smrg * of the window. X11's window coordinate origin is in the upper-left 35848b8605Smrg * corner of the window. Therefore, most drawing functions in this 36848b8605Smrg * file have to flip Y coordinates. 37848b8605Smrg * 38848b8605Smrg * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile 39848b8605Smrg * in support for the MIT Shared Memory extension. If enabled, when you 40848b8605Smrg * use an Ximage for the back buffer in double buffered mode, the "swap" 41848b8605Smrg * operation will be faster. You must also link with -lXext. 42848b8605Smrg * 43848b8605Smrg * Byte swapping: If the Mesa host and the X display use a different 44848b8605Smrg * byte order then there's some trickiness to be aware of when using 45848b8605Smrg * XImages. The byte ordering used for the XImage is that of the X 46848b8605Smrg * display, not the Mesa host. 47848b8605Smrg * The color-to-pixel encoding for True/DirectColor must be done 48848b8605Smrg * according to the display's visual red_mask, green_mask, and blue_mask. 49848b8605Smrg * If XPutPixel is used to put a pixel into an XImage then XPutPixel will 50848b8605Smrg * do byte swapping if needed. If one wants to directly "poke" the pixel 51848b8605Smrg * into the XImage's buffer then the pixel must be byte swapped first. In 52848b8605Smrg * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format 53848b8605Smrg * and use XPutPixel everywhere except in the implementation of 54848b8605Smrg * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so 55848b8605Smrg * instead of using XPutPixel we "poke" our values after byte-swapping 56848b8605Smrg * the clear pixel value if needed. 57848b8605Smrg * 58848b8605Smrg */ 59848b8605Smrg 60848b8605Smrg#ifdef __CYGWIN__ 61848b8605Smrg#undef WIN32 62848b8605Smrg#undef __WIN32__ 63848b8605Smrg#endif 64848b8605Smrg 65b8e80941Smrg#include <stdio.h> 66848b8605Smrg#include "glxheader.h" 67848b8605Smrg#include "xmesaP.h" 68848b8605Smrg#include "main/api_exec.h" 69848b8605Smrg#include "main/context.h" 70848b8605Smrg#include "main/extensions.h" 71848b8605Smrg#include "main/framebuffer.h" 72848b8605Smrg#include "main/imports.h" 73848b8605Smrg#include "main/macros.h" 74848b8605Smrg#include "main/renderbuffer.h" 75848b8605Smrg#include "main/teximage.h" 76848b8605Smrg#include "main/version.h" 77848b8605Smrg#include "main/vtxfmt.h" 78848b8605Smrg#include "swrast/swrast.h" 79848b8605Smrg#include "swrast/s_renderbuffer.h" 80848b8605Smrg#include "swrast_setup/swrast_setup.h" 81848b8605Smrg#include "vbo/vbo.h" 82848b8605Smrg#include "tnl/tnl.h" 83848b8605Smrg#include "tnl/t_context.h" 84848b8605Smrg#include "tnl/t_pipeline.h" 85848b8605Smrg#include "drivers/common/driverfuncs.h" 86848b8605Smrg#include "drivers/common/meta.h" 87b8e80941Smrg#include "util/u_math.h" 88848b8605Smrg 89848b8605Smrg/** 90848b8605Smrg * Global X driver lock 91848b8605Smrg */ 92848b8605Smrgmtx_t _xmesa_lock; 93848b8605Smrg 94848b8605Smrg 95848b8605Smrg 96848b8605Smrg/**********************************************************************/ 97848b8605Smrg/***** X Utility Functions *****/ 98848b8605Smrg/**********************************************************************/ 99848b8605Smrg 100848b8605Smrg 101848b8605Smrg/** 102848b8605Smrg * Return the host's byte order as LSBFirst or MSBFirst ala X. 103848b8605Smrg */ 104848b8605Smrgstatic int host_byte_order( void ) 105848b8605Smrg{ 106848b8605Smrg int i = 1; 107848b8605Smrg char *cptr = (char *) &i; 108848b8605Smrg return (*cptr==1) ? LSBFirst : MSBFirst; 109848b8605Smrg} 110848b8605Smrg 111848b8605Smrg 112848b8605Smrg/** 113848b8605Smrg * Check if the X Shared Memory extension is available. 114848b8605Smrg * Return: 0 = not available 115848b8605Smrg * 1 = shared XImage support available 116848b8605Smrg * 2 = shared Pixmap support available also 117848b8605Smrg */ 118848b8605Smrgstatic int check_for_xshm( XMesaDisplay *display ) 119848b8605Smrg{ 120848b8605Smrg#if defined(USE_XSHM) 121848b8605Smrg int ignore; 122848b8605Smrg 123848b8605Smrg if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { 124848b8605Smrg /* Note: we're no longer calling XShmQueryVersion() here. It seems 125848b8605Smrg * to be flakey (triggers a spurious X protocol error when we close 126848b8605Smrg * one display connection and start using a new one. XShm has been 127848b8605Smrg * around a long time and hasn't changed so if MIT_SHM is supported 128848b8605Smrg * we assume we're good to go. 129848b8605Smrg */ 130848b8605Smrg return 2; 131848b8605Smrg } 132848b8605Smrg else { 133848b8605Smrg return 0; 134848b8605Smrg } 135848b8605Smrg#else 136848b8605Smrg /* No XSHM support */ 137848b8605Smrg return 0; 138848b8605Smrg#endif 139848b8605Smrg} 140848b8605Smrg 141848b8605Smrg 142848b8605Smrg/** 143848b8605Smrg * Apply gamma correction to an intensity value in [0..max]. Return the 144848b8605Smrg * new intensity value. 145848b8605Smrg */ 146848b8605Smrgstatic GLint 147848b8605Smrggamma_adjust( GLfloat gamma, GLint value, GLint max ) 148848b8605Smrg{ 149848b8605Smrg if (gamma == 1.0) { 150848b8605Smrg return value; 151848b8605Smrg } 152848b8605Smrg else { 153848b8605Smrg double x = (double) value / (double) max; 154848b8605Smrg return IROUND_POS((GLfloat) max * pow(x, 1.0F/gamma)); 155848b8605Smrg } 156848b8605Smrg} 157848b8605Smrg 158848b8605Smrg 159848b8605Smrg 160848b8605Smrg/** 161848b8605Smrg * Return the true number of bits per pixel for XImages. 162848b8605Smrg * For example, if we request a 24-bit deep visual we may actually need/get 163848b8605Smrg * 32bpp XImages. This function returns the appropriate bpp. 164848b8605Smrg * Input: dpy - the X display 165848b8605Smrg * visinfo - desribes the visual to be used for XImages 166848b8605Smrg * Return: true number of bits per pixel for XImages 167848b8605Smrg */ 168848b8605Smrgstatic int 169848b8605Smrgbits_per_pixel( XMesaVisual xmv ) 170848b8605Smrg{ 171848b8605Smrg XMesaDisplay *dpy = xmv->display; 172848b8605Smrg XMesaVisualInfo visinfo = xmv->visinfo; 173848b8605Smrg XMesaImage *img; 174848b8605Smrg int bitsPerPixel; 175848b8605Smrg /* Create a temporary XImage */ 176848b8605Smrg img = XCreateImage( dpy, visinfo->visual, visinfo->depth, 177848b8605Smrg ZPixmap, 0, /*format, offset*/ 178848b8605Smrg malloc(8), /*data*/ 179848b8605Smrg 1, 1, /*width, height*/ 180848b8605Smrg 32, /*bitmap_pad*/ 181848b8605Smrg 0 /*bytes_per_line*/ 182848b8605Smrg ); 183848b8605Smrg assert(img); 184848b8605Smrg /* grab the bits/pixel value */ 185848b8605Smrg bitsPerPixel = img->bits_per_pixel; 186848b8605Smrg /* free the XImage */ 187848b8605Smrg free( img->data ); 188848b8605Smrg img->data = NULL; 189848b8605Smrg XMesaDestroyImage( img ); 190848b8605Smrg return bitsPerPixel; 191848b8605Smrg} 192848b8605Smrg 193848b8605Smrg 194848b8605Smrg 195848b8605Smrg/* 196848b8605Smrg * Determine if a given X window ID is valid (window exists). 197848b8605Smrg * Do this by calling XGetWindowAttributes() for the window and 198848b8605Smrg * checking if we catch an X error. 199848b8605Smrg * Input: dpy - the display 200b8e80941Smrg * win - the window to check for existence 201848b8605Smrg * Return: GL_TRUE - window exists 202848b8605Smrg * GL_FALSE - window doesn't exist 203848b8605Smrg */ 204848b8605Smrgstatic GLboolean WindowExistsFlag; 205848b8605Smrg 206848b8605Smrgstatic int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr ) 207848b8605Smrg{ 208848b8605Smrg (void) dpy; 209848b8605Smrg if (xerr->error_code == BadWindow) { 210848b8605Smrg WindowExistsFlag = GL_FALSE; 211848b8605Smrg } 212848b8605Smrg return 0; 213848b8605Smrg} 214848b8605Smrg 215848b8605Smrgstatic GLboolean window_exists( XMesaDisplay *dpy, Window win ) 216848b8605Smrg{ 217848b8605Smrg XWindowAttributes wa; 218848b8605Smrg int (*old_handler)( XMesaDisplay*, XErrorEvent* ); 219848b8605Smrg WindowExistsFlag = GL_TRUE; 220848b8605Smrg old_handler = XSetErrorHandler(window_exists_err_handler); 221848b8605Smrg XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ 222848b8605Smrg XSetErrorHandler(old_handler); 223848b8605Smrg return WindowExistsFlag; 224848b8605Smrg} 225848b8605Smrg 226848b8605Smrgstatic Status 227848b8605Smrgget_drawable_size( XMesaDisplay *dpy, Drawable d, GLuint *width, GLuint *height ) 228848b8605Smrg{ 229848b8605Smrg Window root; 230848b8605Smrg Status stat; 231848b8605Smrg int xpos, ypos; 232848b8605Smrg unsigned int w, h, bw, depth; 233848b8605Smrg stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); 234848b8605Smrg *width = w; 235848b8605Smrg *height = h; 236848b8605Smrg return stat; 237848b8605Smrg} 238848b8605Smrg 239848b8605Smrg 240848b8605Smrg/** 241848b8605Smrg * Return the size of the window (or pixmap) that corresponds to the 242848b8605Smrg * given XMesaBuffer. 243848b8605Smrg * \param width returns width in pixels 244848b8605Smrg * \param height returns height in pixels 245848b8605Smrg */ 246848b8605Smrgvoid 247848b8605Smrgxmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b, 248848b8605Smrg GLuint *width, GLuint *height) 249848b8605Smrg{ 250848b8605Smrg Status stat; 251848b8605Smrg 252848b8605Smrg mtx_lock(&_xmesa_lock); 253848b8605Smrg XSync(b->xm_visual->display, 0); /* added for Chromium */ 254848b8605Smrg stat = get_drawable_size(dpy, b->frontxrb->pixmap, width, height); 255848b8605Smrg mtx_unlock(&_xmesa_lock); 256848b8605Smrg 257848b8605Smrg if (!stat) { 258848b8605Smrg /* probably querying a window that's recently been destroyed */ 259848b8605Smrg _mesa_warning(NULL, "XGetGeometry failed!\n"); 260848b8605Smrg *width = *height = 1; 261848b8605Smrg } 262848b8605Smrg} 263848b8605Smrg 264848b8605Smrg 265848b8605Smrg 266848b8605Smrg/**********************************************************************/ 267848b8605Smrg/***** Linked list of XMesaBuffers *****/ 268848b8605Smrg/**********************************************************************/ 269848b8605Smrg 270848b8605SmrgXMesaBuffer XMesaBufferList = NULL; 271848b8605Smrg 272848b8605Smrg 273848b8605Smrg/** 274848b8605Smrg * Allocate a new XMesaBuffer object which corresponds to the given drawable. 275848b8605Smrg * Note that XMesaBuffer is derived from struct gl_framebuffer. 276848b8605Smrg * The new XMesaBuffer will not have any size (Width=Height=0). 277848b8605Smrg * 278848b8605Smrg * \param d the corresponding X drawable (window or pixmap) 279848b8605Smrg * \param type either WINDOW, PIXMAP or PBUFFER, describing d 280848b8605Smrg * \param vis the buffer's visual 281848b8605Smrg * \param cmap the window's colormap, if known. 282848b8605Smrg * \return new XMesaBuffer or NULL if any problem 283848b8605Smrg */ 284848b8605Smrgstatic XMesaBuffer 285848b8605Smrgcreate_xmesa_buffer(XMesaDrawable d, BufferType type, 286848b8605Smrg XMesaVisual vis, XMesaColormap cmap) 287848b8605Smrg{ 288848b8605Smrg XMesaBuffer b; 289848b8605Smrg 290b8e80941Smrg assert(type == WINDOW || type == PIXMAP || type == PBUFFER); 291848b8605Smrg 292848b8605Smrg b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); 293848b8605Smrg if (!b) 294848b8605Smrg return NULL; 295848b8605Smrg 296848b8605Smrg b->display = vis->display; 297848b8605Smrg b->xm_visual = vis; 298848b8605Smrg b->type = type; 299848b8605Smrg b->cmap = cmap; 300848b8605Smrg 301848b8605Smrg _mesa_initialize_window_framebuffer(&b->mesa_buffer, &vis->mesa_visual); 302848b8605Smrg b->mesa_buffer.Delete = xmesa_delete_framebuffer; 303848b8605Smrg 304848b8605Smrg /* 305848b8605Smrg * Front renderbuffer 306848b8605Smrg */ 307848b8605Smrg b->frontxrb = xmesa_new_renderbuffer(NULL, 0, vis, GL_FALSE); 308848b8605Smrg if (!b->frontxrb) { 309848b8605Smrg free(b); 310848b8605Smrg return NULL; 311848b8605Smrg } 312848b8605Smrg b->frontxrb->Parent = b; 313848b8605Smrg b->frontxrb->drawable = d; 314848b8605Smrg b->frontxrb->pixmap = (XMesaPixmap) d; 315b8e80941Smrg _mesa_attach_and_own_rb(&b->mesa_buffer, BUFFER_FRONT_LEFT, 316b8e80941Smrg &b->frontxrb->Base.Base); 317848b8605Smrg 318848b8605Smrg /* 319848b8605Smrg * Back renderbuffer 320848b8605Smrg */ 321848b8605Smrg if (vis->mesa_visual.doubleBufferMode) { 322848b8605Smrg b->backxrb = xmesa_new_renderbuffer(NULL, 0, vis, GL_TRUE); 323848b8605Smrg if (!b->backxrb) { 324848b8605Smrg /* XXX free front xrb too */ 325848b8605Smrg free(b); 326848b8605Smrg return NULL; 327848b8605Smrg } 328848b8605Smrg b->backxrb->Parent = b; 329848b8605Smrg /* determine back buffer implementation */ 330848b8605Smrg b->db_mode = vis->ximage_flag ? BACK_XIMAGE : BACK_PIXMAP; 331848b8605Smrg 332b8e80941Smrg _mesa_attach_and_own_rb(&b->mesa_buffer, BUFFER_BACK_LEFT, 333b8e80941Smrg &b->backxrb->Base.Base); 334848b8605Smrg } 335848b8605Smrg 336848b8605Smrg /* 337848b8605Smrg * Other renderbuffer (depth, stencil, etc) 338848b8605Smrg */ 339848b8605Smrg _swrast_add_soft_renderbuffers(&b->mesa_buffer, 340848b8605Smrg GL_FALSE, /* color */ 341848b8605Smrg vis->mesa_visual.haveDepthBuffer, 342848b8605Smrg vis->mesa_visual.haveStencilBuffer, 343848b8605Smrg vis->mesa_visual.haveAccumBuffer, 344848b8605Smrg GL_FALSE, /* software alpha buffer */ 345848b8605Smrg vis->mesa_visual.numAuxBuffers > 0 ); 346848b8605Smrg 347848b8605Smrg /* GLX_EXT_texture_from_pixmap */ 348848b8605Smrg b->TextureTarget = 0; 349848b8605Smrg b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; 350848b8605Smrg b->TextureMipmap = 0; 351848b8605Smrg 352848b8605Smrg /* insert buffer into linked list */ 353848b8605Smrg b->Next = XMesaBufferList; 354848b8605Smrg XMesaBufferList = b; 355848b8605Smrg 356848b8605Smrg return b; 357848b8605Smrg} 358848b8605Smrg 359848b8605Smrg 360848b8605Smrg/** 361848b8605Smrg * Find an XMesaBuffer by matching X display and colormap but NOT matching 362848b8605Smrg * the notThis buffer. 363848b8605Smrg */ 364848b8605SmrgXMesaBuffer 365848b8605Smrgxmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis) 366848b8605Smrg{ 367848b8605Smrg XMesaBuffer b; 368848b8605Smrg for (b=XMesaBufferList; b; b=b->Next) { 369848b8605Smrg if (b->display==dpy && b->cmap==cmap && b!=notThis) { 370848b8605Smrg return b; 371848b8605Smrg } 372848b8605Smrg } 373848b8605Smrg return NULL; 374848b8605Smrg} 375848b8605Smrg 376848b8605Smrg 377848b8605Smrg/** 378848b8605Smrg * Remove buffer from linked list, delete if no longer referenced. 379848b8605Smrg */ 380848b8605Smrgstatic void 381848b8605Smrgxmesa_free_buffer(XMesaBuffer buffer) 382848b8605Smrg{ 383848b8605Smrg XMesaBuffer prev = NULL, b; 384848b8605Smrg 385848b8605Smrg for (b = XMesaBufferList; b; b = b->Next) { 386848b8605Smrg if (b == buffer) { 387848b8605Smrg struct gl_framebuffer *fb = &buffer->mesa_buffer; 388848b8605Smrg 389848b8605Smrg /* unlink buffer from list */ 390848b8605Smrg if (prev) 391848b8605Smrg prev->Next = buffer->Next; 392848b8605Smrg else 393848b8605Smrg XMesaBufferList = buffer->Next; 394848b8605Smrg 395848b8605Smrg /* mark as delete pending */ 396848b8605Smrg fb->DeletePending = GL_TRUE; 397848b8605Smrg 398848b8605Smrg /* Since the X window for the XMesaBuffer is going away, we don't 399848b8605Smrg * want to dereference this pointer in the future. 400848b8605Smrg */ 401848b8605Smrg b->frontxrb->drawable = 0; 402848b8605Smrg 403848b8605Smrg /* Unreference. If count = zero we'll really delete the buffer */ 404848b8605Smrg _mesa_reference_framebuffer(&fb, NULL); 405848b8605Smrg 406848b8605Smrg return; 407848b8605Smrg } 408848b8605Smrg /* continue search */ 409848b8605Smrg prev = b; 410848b8605Smrg } 411848b8605Smrg /* buffer not found in XMesaBufferList */ 412848b8605Smrg _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); 413848b8605Smrg} 414848b8605Smrg 415848b8605Smrg 416848b8605Smrg 417848b8605Smrg 418848b8605Smrg/**********************************************************************/ 419848b8605Smrg/***** Misc Private Functions *****/ 420848b8605Smrg/**********************************************************************/ 421848b8605Smrg 422848b8605Smrg 423848b8605Smrg/** 424848b8605Smrg * Setup RGB rendering for a window with a True/DirectColor visual. 425848b8605Smrg */ 426848b8605Smrgstatic void 427848b8605Smrgsetup_truecolor(XMesaVisual v, XMesaBuffer buffer, XMesaColormap cmap) 428848b8605Smrg{ 429848b8605Smrg unsigned long rmask, gmask, bmask; 430848b8605Smrg (void) buffer; 431848b8605Smrg (void) cmap; 432848b8605Smrg 433848b8605Smrg /* Compute red multiplier (mask) and bit shift */ 434848b8605Smrg v->rshift = 0; 435848b8605Smrg rmask = GET_REDMASK(v); 436848b8605Smrg while ((rmask & 1)==0) { 437848b8605Smrg v->rshift++; 438848b8605Smrg rmask = rmask >> 1; 439848b8605Smrg } 440848b8605Smrg 441848b8605Smrg /* Compute green multiplier (mask) and bit shift */ 442848b8605Smrg v->gshift = 0; 443848b8605Smrg gmask = GET_GREENMASK(v); 444848b8605Smrg while ((gmask & 1)==0) { 445848b8605Smrg v->gshift++; 446848b8605Smrg gmask = gmask >> 1; 447848b8605Smrg } 448848b8605Smrg 449848b8605Smrg /* Compute blue multiplier (mask) and bit shift */ 450848b8605Smrg v->bshift = 0; 451848b8605Smrg bmask = GET_BLUEMASK(v); 452848b8605Smrg while ((bmask & 1)==0) { 453848b8605Smrg v->bshift++; 454848b8605Smrg bmask = bmask >> 1; 455848b8605Smrg } 456848b8605Smrg 457848b8605Smrg /* 458848b8605Smrg * Compute component-to-pixel lookup tables and dithering kernel 459848b8605Smrg */ 460848b8605Smrg { 461848b8605Smrg static GLubyte kernel[16] = { 462848b8605Smrg 0*16, 8*16, 2*16, 10*16, 463848b8605Smrg 12*16, 4*16, 14*16, 6*16, 464848b8605Smrg 3*16, 11*16, 1*16, 9*16, 465848b8605Smrg 15*16, 7*16, 13*16, 5*16, 466848b8605Smrg }; 467b8e80941Smrg GLint rBits = util_bitcount(rmask); 468b8e80941Smrg GLint gBits = util_bitcount(gmask); 469b8e80941Smrg GLint bBits = util_bitcount(bmask); 470848b8605Smrg GLint maxBits; 471848b8605Smrg GLuint i; 472848b8605Smrg 473848b8605Smrg /* convert pixel components in [0,_mask] to RGB values in [0,255] */ 474848b8605Smrg for (i=0; i<=rmask; i++) 475848b8605Smrg v->PixelToR[i] = (unsigned char) ((i * 255) / rmask); 476848b8605Smrg for (i=0; i<=gmask; i++) 477848b8605Smrg v->PixelToG[i] = (unsigned char) ((i * 255) / gmask); 478848b8605Smrg for (i=0; i<=bmask; i++) 479848b8605Smrg v->PixelToB[i] = (unsigned char) ((i * 255) / bmask); 480848b8605Smrg 481848b8605Smrg /* convert RGB values from [0,255] to pixel components */ 482848b8605Smrg 483848b8605Smrg for (i=0;i<256;i++) { 484848b8605Smrg GLint r = gamma_adjust(v->RedGamma, i, 255); 485848b8605Smrg GLint g = gamma_adjust(v->GreenGamma, i, 255); 486848b8605Smrg GLint b = gamma_adjust(v->BlueGamma, i, 255); 487848b8605Smrg v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift; 488848b8605Smrg v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift; 489848b8605Smrg v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift; 490848b8605Smrg } 491848b8605Smrg /* overflow protection */ 492848b8605Smrg for (i=256;i<512;i++) { 493848b8605Smrg v->RtoPixel[i] = v->RtoPixel[255]; 494848b8605Smrg v->GtoPixel[i] = v->GtoPixel[255]; 495848b8605Smrg v->BtoPixel[i] = v->BtoPixel[255]; 496848b8605Smrg } 497848b8605Smrg 498848b8605Smrg /* setup dithering kernel */ 499848b8605Smrg maxBits = rBits; 500848b8605Smrg if (gBits > maxBits) maxBits = gBits; 501848b8605Smrg if (bBits > maxBits) maxBits = bBits; 502848b8605Smrg for (i=0;i<16;i++) { 503848b8605Smrg v->Kernel[i] = kernel[i] >> maxBits; 504848b8605Smrg } 505848b8605Smrg 506848b8605Smrg v->undithered_pf = PF_Truecolor; 507848b8605Smrg v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor; 508848b8605Smrg } 509848b8605Smrg 510848b8605Smrg /* 511848b8605Smrg * Now check for TrueColor visuals which we can optimize. 512848b8605Smrg */ 513848b8605Smrg if ( GET_REDMASK(v) ==0x0000ff 514848b8605Smrg && GET_GREENMASK(v)==0x00ff00 515848b8605Smrg && GET_BLUEMASK(v) ==0xff0000 516848b8605Smrg && CHECK_BYTE_ORDER(v) 517848b8605Smrg && v->BitsPerPixel==32 518848b8605Smrg && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 519848b8605Smrg /* common 32 bpp config used on SGI, Sun */ 520848b8605Smrg v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; /* ABGR */ 521848b8605Smrg } 522848b8605Smrg else if (GET_REDMASK(v) == 0xff0000 523848b8605Smrg && GET_GREENMASK(v)== 0x00ff00 524848b8605Smrg && GET_BLUEMASK(v) == 0x0000ff 525848b8605Smrg && CHECK_BYTE_ORDER(v) 526848b8605Smrg && v->RedGamma == 1.0 && v->GreenGamma == 1.0 && v->BlueGamma == 1.0){ 527848b8605Smrg if (v->BitsPerPixel==32) { 528848b8605Smrg /* if 32 bpp, and visual indicates 8 bpp alpha channel */ 529848b8605Smrg if (GET_VISUAL_DEPTH(v) == 32 && v->mesa_visual.alphaBits == 8) 530848b8605Smrg v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; /* ARGB */ 531848b8605Smrg else 532848b8605Smrg v->undithered_pf = v->dithered_pf = PF_8R8G8B; /* xRGB */ 533848b8605Smrg } 534848b8605Smrg else if (v->BitsPerPixel == 24) { 535848b8605Smrg v->undithered_pf = v->dithered_pf = PF_8R8G8B24; /* RGB */ 536848b8605Smrg } 537848b8605Smrg } 538848b8605Smrg else if (GET_REDMASK(v) ==0xf800 539848b8605Smrg && GET_GREENMASK(v)==0x07e0 540848b8605Smrg && GET_BLUEMASK(v) ==0x001f 541848b8605Smrg && CHECK_BYTE_ORDER(v) 542848b8605Smrg && v->BitsPerPixel==16 543848b8605Smrg && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { 544848b8605Smrg /* 5-6-5 RGB */ 545848b8605Smrg v->undithered_pf = PF_5R6G5B; 546848b8605Smrg v->dithered_pf = PF_Dither_5R6G5B; 547848b8605Smrg } 548848b8605Smrg} 549848b8605Smrg 550848b8605Smrg 551848b8605Smrg/** 552848b8605Smrg * When a context is bound for the first time, we can finally finish 553848b8605Smrg * initializing the context's visual and buffer information. 554848b8605Smrg * \param v the XMesaVisual to initialize 555848b8605Smrg * \param b the XMesaBuffer to initialize (may be NULL) 556848b8605Smrg * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode 557848b8605Smrg * \param window the window/pixmap we're rendering into 558848b8605Smrg * \param cmap the colormap associated with the window/pixmap 559848b8605Smrg * \return GL_TRUE=success, GL_FALSE=failure 560848b8605Smrg */ 561848b8605Smrgstatic GLboolean 562848b8605Smrginitialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, 563848b8605Smrg XMesaDrawable window, 564848b8605Smrg XMesaColormap cmap) 565848b8605Smrg{ 566848b8605Smrg const int xclass = v->visualType; 567848b8605Smrg 568848b8605Smrg 569b8e80941Smrg assert(!b || b->xm_visual == v); 570848b8605Smrg 571848b8605Smrg /* Save true bits/pixel */ 572848b8605Smrg v->BitsPerPixel = bits_per_pixel(v); 573848b8605Smrg assert(v->BitsPerPixel > 0); 574848b8605Smrg 575848b8605Smrg /* RGB WINDOW: 576848b8605Smrg * We support RGB rendering into almost any kind of visual. 577848b8605Smrg */ 578848b8605Smrg if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { 579848b8605Smrg setup_truecolor( v, b, cmap ); 580848b8605Smrg } 581848b8605Smrg else { 582848b8605Smrg _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n"); 583848b8605Smrg return GL_FALSE; 584848b8605Smrg } 585848b8605Smrg v->mesa_visual.indexBits = 0; 586848b8605Smrg 587b8e80941Smrg if (getenv("MESA_NO_DITHER")) { 588848b8605Smrg v->dithered_pf = v->undithered_pf; 589848b8605Smrg } 590848b8605Smrg 591848b8605Smrg 592848b8605Smrg /* 593848b8605Smrg * If MESA_INFO env var is set print out some debugging info 594848b8605Smrg * which can help Brian figure out what's going on when a user 595848b8605Smrg * reports bugs. 596848b8605Smrg */ 597b8e80941Smrg if (getenv("MESA_INFO")) { 598848b8605Smrg printf("X/Mesa visual = %p\n", (void *) v); 599848b8605Smrg printf("X/Mesa dithered pf = %u\n", v->dithered_pf); 600848b8605Smrg printf("X/Mesa undithered pf = %u\n", v->undithered_pf); 601848b8605Smrg printf("X/Mesa level = %d\n", v->mesa_visual.level); 602848b8605Smrg printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v)); 603848b8605Smrg printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); 604848b8605Smrg } 605848b8605Smrg 606848b8605Smrg if (b && window) { 607848b8605Smrg /* Do window-specific initializations */ 608848b8605Smrg 609848b8605Smrg /* these should have been set in create_xmesa_buffer */ 610b8e80941Smrg assert(b->frontxrb->drawable == window); 611b8e80941Smrg assert(b->frontxrb->pixmap == (XMesaPixmap) window); 612848b8605Smrg 613848b8605Smrg /* Setup for single/double buffering */ 614848b8605Smrg if (v->mesa_visual.doubleBufferMode) { 615848b8605Smrg /* Double buffered */ 616848b8605Smrg b->shm = check_for_xshm( v->display ); 617848b8605Smrg } 618848b8605Smrg 619848b8605Smrg /* X11 graphics contexts */ 620848b8605Smrg b->gc = XCreateGC( v->display, window, 0, NULL ); 621848b8605Smrg XMesaSetFunction( v->display, b->gc, GXcopy ); 622848b8605Smrg 623848b8605Smrg /* cleargc - for glClear() */ 624848b8605Smrg b->cleargc = XCreateGC( v->display, window, 0, NULL ); 625848b8605Smrg XMesaSetFunction( v->display, b->cleargc, GXcopy ); 626848b8605Smrg 627848b8605Smrg /* 628848b8605Smrg * Don't generate Graphics Expose/NoExpose events in swapbuffers(). 629848b8605Smrg * Patch contributed by Michael Pichler May 15, 1995. 630848b8605Smrg */ 631848b8605Smrg { 632848b8605Smrg XGCValues gcvalues; 633848b8605Smrg gcvalues.graphics_exposures = False; 634848b8605Smrg b->swapgc = XCreateGC(v->display, window, 635848b8605Smrg GCGraphicsExposures, &gcvalues); 636848b8605Smrg } 637848b8605Smrg XMesaSetFunction( v->display, b->swapgc, GXcopy ); 638848b8605Smrg } 639848b8605Smrg 640848b8605Smrg return GL_TRUE; 641848b8605Smrg} 642848b8605Smrg 643848b8605Smrg 644848b8605Smrg 645848b8605Smrg/* 646848b8605Smrg * Convert an RGBA color to a pixel value. 647848b8605Smrg */ 648848b8605Smrgunsigned long 649848b8605Smrgxmesa_color_to_pixel(struct gl_context *ctx, 650848b8605Smrg GLubyte r, GLubyte g, GLubyte b, GLubyte a, 651848b8605Smrg GLuint pixelFormat) 652848b8605Smrg{ 653848b8605Smrg XMesaContext xmesa = XMESA_CONTEXT(ctx); 654848b8605Smrg switch (pixelFormat) { 655848b8605Smrg case PF_Truecolor: 656848b8605Smrg { 657848b8605Smrg unsigned long p; 658848b8605Smrg PACK_TRUECOLOR( p, r, g, b ); 659848b8605Smrg return p; 660848b8605Smrg } 661848b8605Smrg case PF_8A8B8G8R: 662848b8605Smrg return PACK_8A8B8G8R( r, g, b, a ); 663848b8605Smrg case PF_8A8R8G8B: 664848b8605Smrg return PACK_8A8R8G8B( r, g, b, a ); 665848b8605Smrg case PF_8R8G8B: 666848b8605Smrg /* fall through */ 667848b8605Smrg case PF_8R8G8B24: 668848b8605Smrg return PACK_8R8G8B( r, g, b ); 669848b8605Smrg case PF_5R6G5B: 670848b8605Smrg return PACK_5R6G5B( r, g, b ); 671848b8605Smrg case PF_Dither_True: 672848b8605Smrg /* fall through */ 673848b8605Smrg case PF_Dither_5R6G5B: 674848b8605Smrg { 675848b8605Smrg unsigned long p; 676848b8605Smrg PACK_TRUEDITHER(p, 1, 0, r, g, b); 677848b8605Smrg return p; 678848b8605Smrg } 679848b8605Smrg default: 680848b8605Smrg _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel"); 681848b8605Smrg } 682848b8605Smrg return 0; 683848b8605Smrg} 684848b8605Smrg 685848b8605Smrg 686848b8605Smrg#define NUM_VISUAL_TYPES 6 687848b8605Smrg 688848b8605Smrg/** 689848b8605Smrg * Convert an X visual type to a GLX visual type. 690848b8605Smrg * 691848b8605Smrg * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) 692848b8605Smrg * to be converted. 693848b8605Smrg * \return If \c visualType is a valid X visual type, a GLX visual type will 694848b8605Smrg * be returned. Otherwise \c GLX_NONE will be returned. 695848b8605Smrg * 696848b8605Smrg * \note 697848b8605Smrg * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the 698848b8605Smrg * DRI CVS tree. 699848b8605Smrg */ 700848b8605Smrgstatic GLint 701848b8605Smrgxmesa_convert_from_x_visual_type( int visualType ) 702848b8605Smrg{ 703848b8605Smrg static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { 704848b8605Smrg GLX_STATIC_GRAY, GLX_GRAY_SCALE, 705848b8605Smrg GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, 706848b8605Smrg GLX_TRUE_COLOR, GLX_DIRECT_COLOR 707848b8605Smrg }; 708848b8605Smrg 709848b8605Smrg return ( (unsigned) visualType < NUM_VISUAL_TYPES ) 710848b8605Smrg ? glx_visual_types[ visualType ] : GLX_NONE; 711848b8605Smrg} 712848b8605Smrg 713848b8605Smrg 714848b8605Smrg/**********************************************************************/ 715848b8605Smrg/***** Public Functions *****/ 716848b8605Smrg/**********************************************************************/ 717848b8605Smrg 718848b8605Smrg 719848b8605Smrg/* 720848b8605Smrg * Create a new X/Mesa visual. 721848b8605Smrg * Input: display - X11 display 722848b8605Smrg * visinfo - an XVisualInfo pointer 723848b8605Smrg * rgb_flag - GL_TRUE = RGB mode, 724848b8605Smrg * GL_FALSE = color index mode 725848b8605Smrg * alpha_flag - alpha buffer requested? 726848b8605Smrg * db_flag - GL_TRUE = double-buffered, 727848b8605Smrg * GL_FALSE = single buffered 728848b8605Smrg * stereo_flag - stereo visual? 729848b8605Smrg * ximage_flag - GL_TRUE = use an XImage for back buffer, 730848b8605Smrg * GL_FALSE = use an off-screen pixmap for back buffer 731848b8605Smrg * depth_size - requested bits/depth values, or zero 732848b8605Smrg * stencil_size - requested bits/stencil values, or zero 733848b8605Smrg * accum_red_size - requested bits/red accum values, or zero 734848b8605Smrg * accum_green_size - requested bits/green accum values, or zero 735848b8605Smrg * accum_blue_size - requested bits/blue accum values, or zero 736848b8605Smrg * accum_alpha_size - requested bits/alpha accum values, or zero 737848b8605Smrg * num_samples - number of samples/pixel if multisampling, or zero 738848b8605Smrg * level - visual level, usually 0 739848b8605Smrg * visualCaveat - ala the GLX extension, usually GLX_NONE 740848b8605Smrg * Return; a new XMesaVisual or 0 if error. 741848b8605Smrg */ 742848b8605SmrgPUBLIC 743848b8605SmrgXMesaVisual XMesaCreateVisual( XMesaDisplay *display, 744848b8605Smrg XMesaVisualInfo visinfo, 745848b8605Smrg GLboolean rgb_flag, 746848b8605Smrg GLboolean alpha_flag, 747848b8605Smrg GLboolean db_flag, 748848b8605Smrg GLboolean stereo_flag, 749848b8605Smrg GLboolean ximage_flag, 750848b8605Smrg GLint depth_size, 751848b8605Smrg GLint stencil_size, 752848b8605Smrg GLint accum_red_size, 753848b8605Smrg GLint accum_green_size, 754848b8605Smrg GLint accum_blue_size, 755848b8605Smrg GLint accum_alpha_size, 756848b8605Smrg GLint num_samples, 757848b8605Smrg GLint level, 758848b8605Smrg GLint visualCaveat ) 759848b8605Smrg{ 760848b8605Smrg char *gamma; 761848b8605Smrg XMesaVisual v; 762848b8605Smrg GLint red_bits, green_bits, blue_bits, alpha_bits; 763848b8605Smrg 764848b8605Smrg /* For debugging only */ 765b8e80941Smrg if (getenv("MESA_XSYNC")) { 766848b8605Smrg /* This makes debugging X easier. 767848b8605Smrg * In your debugger, set a breakpoint on _XError to stop when an 768848b8605Smrg * X protocol error is generated. 769848b8605Smrg */ 770848b8605Smrg XSynchronize( display, 1 ); 771848b8605Smrg } 772848b8605Smrg 773848b8605Smrg /* Color-index rendering not supported. */ 774848b8605Smrg if (!rgb_flag) 775848b8605Smrg return NULL; 776848b8605Smrg 777848b8605Smrg v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); 778848b8605Smrg if (!v) { 779848b8605Smrg return NULL; 780848b8605Smrg } 781848b8605Smrg 782848b8605Smrg v->display = display; 783848b8605Smrg 784848b8605Smrg /* Save a copy of the XVisualInfo struct because the user may Xfree() 785848b8605Smrg * the struct but we may need some of the information contained in it 786848b8605Smrg * at a later time. 787848b8605Smrg */ 788b8e80941Smrg v->visinfo = malloc(sizeof(*visinfo)); 789848b8605Smrg if(!v->visinfo) { 790848b8605Smrg free(v); 791848b8605Smrg return NULL; 792848b8605Smrg } 793848b8605Smrg memcpy(v->visinfo, visinfo, sizeof(*visinfo)); 794848b8605Smrg 795848b8605Smrg /* check for MESA_GAMMA environment variable */ 796b8e80941Smrg gamma = getenv("MESA_GAMMA"); 797848b8605Smrg if (gamma) { 798848b8605Smrg v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; 799848b8605Smrg sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); 800848b8605Smrg if (v->RedGamma<=0.0) v->RedGamma = 1.0; 801848b8605Smrg if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; 802848b8605Smrg if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; 803848b8605Smrg } 804848b8605Smrg else { 805848b8605Smrg v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; 806848b8605Smrg } 807848b8605Smrg 808848b8605Smrg v->ximage_flag = ximage_flag; 809848b8605Smrg 810848b8605Smrg v->mesa_visual.redMask = visinfo->red_mask; 811848b8605Smrg v->mesa_visual.greenMask = visinfo->green_mask; 812848b8605Smrg v->mesa_visual.blueMask = visinfo->blue_mask; 813848b8605Smrg v->visualID = visinfo->visualid; 814848b8605Smrg v->screen = visinfo->screen; 815848b8605Smrg 816848b8605Smrg#if !(defined(__cplusplus) || defined(c_plusplus)) 817848b8605Smrg v->visualType = xmesa_convert_from_x_visual_type(visinfo->class); 818848b8605Smrg#else 819848b8605Smrg v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); 820848b8605Smrg#endif 821848b8605Smrg 822848b8605Smrg v->mesa_visual.visualRating = visualCaveat; 823848b8605Smrg 824848b8605Smrg if (alpha_flag) 825848b8605Smrg v->mesa_visual.alphaBits = 8; 826848b8605Smrg 827848b8605Smrg (void) initialize_visual_and_buffer( v, NULL, 0, 0 ); 828848b8605Smrg 829848b8605Smrg { 830848b8605Smrg const int xclass = v->visualType; 831848b8605Smrg if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { 832b8e80941Smrg red_bits = util_bitcount(GET_REDMASK(v)); 833b8e80941Smrg green_bits = util_bitcount(GET_GREENMASK(v)); 834b8e80941Smrg blue_bits = util_bitcount(GET_BLUEMASK(v)); 835848b8605Smrg } 836848b8605Smrg else { 837848b8605Smrg /* this is an approximation */ 838848b8605Smrg int depth; 839848b8605Smrg depth = GET_VISUAL_DEPTH(v); 840848b8605Smrg red_bits = depth / 3; 841848b8605Smrg depth -= red_bits; 842848b8605Smrg green_bits = depth / 2; 843848b8605Smrg depth -= green_bits; 844848b8605Smrg blue_bits = depth; 845848b8605Smrg alpha_bits = 0; 846848b8605Smrg assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); 847848b8605Smrg } 848848b8605Smrg alpha_bits = v->mesa_visual.alphaBits; 849848b8605Smrg } 850848b8605Smrg 851848b8605Smrg if (!_mesa_initialize_visual(&v->mesa_visual, 852848b8605Smrg db_flag, stereo_flag, 853848b8605Smrg red_bits, green_bits, 854848b8605Smrg blue_bits, alpha_bits, 855848b8605Smrg depth_size, 856848b8605Smrg stencil_size, 857848b8605Smrg accum_red_size, accum_green_size, 858848b8605Smrg accum_blue_size, accum_alpha_size, 859848b8605Smrg 0)) { 860b8e80941Smrg free(v->visinfo); 861848b8605Smrg free(v); 862848b8605Smrg return NULL; 863848b8605Smrg } 864848b8605Smrg 865848b8605Smrg /* XXX minor hack */ 866848b8605Smrg v->mesa_visual.level = level; 867848b8605Smrg return v; 868848b8605Smrg} 869848b8605Smrg 870848b8605Smrg 871848b8605SmrgPUBLIC 872848b8605Smrgvoid XMesaDestroyVisual( XMesaVisual v ) 873848b8605Smrg{ 874848b8605Smrg free(v->visinfo); 875848b8605Smrg free(v); 876848b8605Smrg} 877848b8605Smrg 878848b8605Smrg 879848b8605Smrg 880848b8605Smrg/** 881848b8605Smrg * Create a new XMesaContext. 882848b8605Smrg * \param v the XMesaVisual 883848b8605Smrg * \param share_list another XMesaContext with which to share display 884848b8605Smrg * lists or NULL if no sharing is wanted. 885848b8605Smrg * \return an XMesaContext or NULL if error. 886848b8605Smrg */ 887848b8605SmrgPUBLIC 888848b8605SmrgXMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) 889848b8605Smrg{ 890848b8605Smrg static GLboolean firstTime = GL_TRUE; 891848b8605Smrg XMesaContext c; 892848b8605Smrg struct gl_context *mesaCtx; 893848b8605Smrg struct dd_function_table functions; 894848b8605Smrg TNLcontext *tnl; 895848b8605Smrg 896848b8605Smrg if (firstTime) { 897848b8605Smrg mtx_init(&_xmesa_lock, mtx_plain); 898848b8605Smrg firstTime = GL_FALSE; 899848b8605Smrg } 900848b8605Smrg 901848b8605Smrg /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */ 902848b8605Smrg c = (XMesaContext) CALLOC_STRUCT(xmesa_context); 903848b8605Smrg if (!c) 904848b8605Smrg return NULL; 905848b8605Smrg 906848b8605Smrg mesaCtx = &(c->mesa); 907848b8605Smrg 908848b8605Smrg /* initialize with default driver functions, then plug in XMesa funcs */ 909848b8605Smrg _mesa_init_driver_functions(&functions); 910b8e80941Smrg _tnl_init_driver_draw_function(&functions); 911848b8605Smrg xmesa_init_driver_functions(v, &functions); 912848b8605Smrg if (!_mesa_initialize_context(mesaCtx, API_OPENGL_COMPAT, &v->mesa_visual, 913848b8605Smrg share_list ? &(share_list->mesa) : (struct gl_context *) NULL, 914848b8605Smrg &functions)) { 915848b8605Smrg free(c); 916848b8605Smrg return NULL; 917848b8605Smrg } 918848b8605Smrg 919848b8605Smrg /* Enable this to exercise fixed function -> shader translation 920848b8605Smrg * with software rendering. 921848b8605Smrg */ 922848b8605Smrg if (0) { 923848b8605Smrg mesaCtx->VertexProgram._MaintainTnlProgram = GL_TRUE; 924848b8605Smrg mesaCtx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; 925848b8605Smrg } 926848b8605Smrg 927848b8605Smrg _mesa_enable_sw_extensions(mesaCtx); 928848b8605Smrg 929848b8605Smrg#if ENABLE_EXT_timer_query 930848b8605Smrg mesaCtx->Extensions.EXT_timer_query = GL_TRUE; 931848b8605Smrg#endif 932848b8605Smrg 933848b8605Smrg 934848b8605Smrg /* finish up xmesa context initializations */ 935848b8605Smrg c->direct = GL_TRUE; 936848b8605Smrg c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE; 937848b8605Smrg c->xm_visual = v; 938848b8605Smrg c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ 939848b8605Smrg c->display = v->display; 940848b8605Smrg c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ 941848b8605Smrg 942848b8605Smrg /* Initialize the software rasterizer and helper modules. 943848b8605Smrg */ 944848b8605Smrg if (!_swrast_CreateContext( mesaCtx ) || 945848b8605Smrg !_vbo_CreateContext( mesaCtx ) || 946848b8605Smrg !_tnl_CreateContext( mesaCtx ) || 947848b8605Smrg !_swsetup_CreateContext( mesaCtx )) { 948b8e80941Smrg _mesa_free_context_data(&c->mesa, true); 949848b8605Smrg free(c); 950848b8605Smrg return NULL; 951848b8605Smrg } 952848b8605Smrg 953848b8605Smrg /* tnl setup */ 954848b8605Smrg tnl = TNL_CONTEXT(mesaCtx); 955848b8605Smrg tnl->Driver.RunPipeline = _tnl_run_pipeline; 956848b8605Smrg /* swrast setup */ 957848b8605Smrg xmesa_register_swrast_functions( mesaCtx ); 958848b8605Smrg _swsetup_Wakeup(mesaCtx); 959848b8605Smrg 960848b8605Smrg _mesa_meta_init(mesaCtx); 961848b8605Smrg 962b8e80941Smrg _mesa_override_extensions(mesaCtx); 963848b8605Smrg _mesa_compute_version(mesaCtx); 964848b8605Smrg 965848b8605Smrg /* Exec table initialization requires the version to be computed */ 966848b8605Smrg _mesa_initialize_dispatch_tables(mesaCtx); 967848b8605Smrg _mesa_initialize_vbo_vtxfmt(mesaCtx); 968848b8605Smrg 969848b8605Smrg return c; 970848b8605Smrg} 971848b8605Smrg 972848b8605Smrg 973848b8605Smrg 974848b8605SmrgPUBLIC 975848b8605Smrgvoid XMesaDestroyContext( XMesaContext c ) 976848b8605Smrg{ 977848b8605Smrg struct gl_context *mesaCtx = &c->mesa; 978848b8605Smrg 979848b8605Smrg _mesa_meta_free( mesaCtx ); 980848b8605Smrg 981848b8605Smrg _swsetup_DestroyContext( mesaCtx ); 982848b8605Smrg _swrast_DestroyContext( mesaCtx ); 983848b8605Smrg _tnl_DestroyContext( mesaCtx ); 984848b8605Smrg _vbo_DestroyContext( mesaCtx ); 985b8e80941Smrg _mesa_free_context_data(mesaCtx, true); 986848b8605Smrg free( c ); 987848b8605Smrg} 988848b8605Smrg 989848b8605Smrg 990848b8605Smrg 991848b8605Smrg/** 992848b8605Smrg * Private function for creating an XMesaBuffer which corresponds to an 993848b8605Smrg * X window or pixmap. 994848b8605Smrg * \param v the window's XMesaVisual 995848b8605Smrg * \param w the window we're wrapping 996848b8605Smrg * \return new XMesaBuffer or NULL if error 997848b8605Smrg */ 998848b8605SmrgPUBLIC XMesaBuffer 999848b8605SmrgXMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) 1000848b8605Smrg{ 1001848b8605Smrg XWindowAttributes attr; 1002848b8605Smrg XMesaBuffer b; 1003848b8605Smrg XMesaColormap cmap; 1004848b8605Smrg int depth; 1005848b8605Smrg 1006848b8605Smrg assert(v); 1007848b8605Smrg assert(w); 1008848b8605Smrg 1009848b8605Smrg /* Check that window depth matches visual depth */ 1010848b8605Smrg XGetWindowAttributes( v->display, w, &attr ); 1011848b8605Smrg depth = attr.depth; 1012848b8605Smrg if (GET_VISUAL_DEPTH(v) != depth) { 1013848b8605Smrg _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", 1014848b8605Smrg GET_VISUAL_DEPTH(v), depth); 1015848b8605Smrg return NULL; 1016848b8605Smrg } 1017848b8605Smrg 1018848b8605Smrg /* Find colormap */ 1019848b8605Smrg if (attr.colormap) { 1020848b8605Smrg cmap = attr.colormap; 1021848b8605Smrg } 1022848b8605Smrg else { 1023848b8605Smrg _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); 1024848b8605Smrg /* this is weird, a window w/out a colormap!? */ 1025848b8605Smrg /* OK, let's just allocate a new one and hope for the best */ 1026848b8605Smrg cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); 1027848b8605Smrg } 1028848b8605Smrg 1029848b8605Smrg b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap); 1030848b8605Smrg if (!b) 1031848b8605Smrg return NULL; 1032848b8605Smrg 1033848b8605Smrg if (!initialize_visual_and_buffer( v, b, (XMesaDrawable) w, cmap )) { 1034848b8605Smrg xmesa_free_buffer(b); 1035848b8605Smrg return NULL; 1036848b8605Smrg } 1037848b8605Smrg 1038848b8605Smrg return b; 1039848b8605Smrg} 1040848b8605Smrg 1041848b8605Smrg 1042848b8605Smrg 1043848b8605Smrg/** 1044848b8605Smrg * Create a new XMesaBuffer from an X pixmap. 1045848b8605Smrg * 1046848b8605Smrg * \param v the XMesaVisual 1047848b8605Smrg * \param p the pixmap 1048848b8605Smrg * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or 1049848b8605Smrg * \c GLX_DIRECT_COLOR visual for the pixmap 1050848b8605Smrg * \returns new XMesaBuffer or NULL if error 1051848b8605Smrg */ 1052848b8605SmrgPUBLIC XMesaBuffer 1053848b8605SmrgXMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap) 1054848b8605Smrg{ 1055848b8605Smrg XMesaBuffer b; 1056848b8605Smrg 1057848b8605Smrg assert(v); 1058848b8605Smrg 1059848b8605Smrg b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); 1060848b8605Smrg if (!b) 1061848b8605Smrg return NULL; 1062848b8605Smrg 1063848b8605Smrg if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) { 1064848b8605Smrg xmesa_free_buffer(b); 1065848b8605Smrg return NULL; 1066848b8605Smrg } 1067848b8605Smrg 1068848b8605Smrg return b; 1069848b8605Smrg} 1070848b8605Smrg 1071848b8605Smrg 1072848b8605Smrg/** 1073848b8605Smrg * For GLX_EXT_texture_from_pixmap 1074848b8605Smrg */ 1075848b8605SmrgXMesaBuffer 1076848b8605SmrgXMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p, 1077848b8605Smrg XMesaColormap cmap, 1078848b8605Smrg int format, int target, int mipmap) 1079848b8605Smrg{ 1080848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1081848b8605Smrg XMesaBuffer b; 1082848b8605Smrg GLuint width, height; 1083848b8605Smrg 1084848b8605Smrg assert(v); 1085848b8605Smrg 1086848b8605Smrg b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); 1087848b8605Smrg if (!b) 1088848b8605Smrg return NULL; 1089848b8605Smrg 1090848b8605Smrg /* get pixmap size, update framebuffer/renderbuffer dims */ 1091848b8605Smrg xmesa_get_window_size(v->display, b, &width, &height); 1092848b8605Smrg _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height); 1093848b8605Smrg 1094848b8605Smrg if (target == 0) { 1095848b8605Smrg /* examine dims */ 1096848b8605Smrg if (ctx->Extensions.ARB_texture_non_power_of_two) { 1097848b8605Smrg target = GLX_TEXTURE_2D_EXT; 1098848b8605Smrg } 1099b8e80941Smrg else if ( util_bitcount(width) == 1 1100b8e80941Smrg && util_bitcount(height) == 1) { 1101848b8605Smrg /* power of two size */ 1102848b8605Smrg if (height == 1) { 1103848b8605Smrg target = GLX_TEXTURE_1D_EXT; 1104848b8605Smrg } 1105848b8605Smrg else { 1106848b8605Smrg target = GLX_TEXTURE_2D_EXT; 1107848b8605Smrg } 1108848b8605Smrg } 1109848b8605Smrg else if (ctx->Extensions.NV_texture_rectangle) { 1110848b8605Smrg target = GLX_TEXTURE_RECTANGLE_EXT; 1111848b8605Smrg } 1112848b8605Smrg else { 1113848b8605Smrg /* non power of two textures not supported */ 1114848b8605Smrg XMesaDestroyBuffer(b); 1115848b8605Smrg return 0; 1116848b8605Smrg } 1117848b8605Smrg } 1118848b8605Smrg 1119848b8605Smrg b->TextureTarget = target; 1120848b8605Smrg b->TextureFormat = format; 1121848b8605Smrg b->TextureMipmap = mipmap; 1122848b8605Smrg 1123848b8605Smrg if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) { 1124848b8605Smrg xmesa_free_buffer(b); 1125848b8605Smrg return NULL; 1126848b8605Smrg } 1127848b8605Smrg 1128848b8605Smrg return b; 1129848b8605Smrg} 1130848b8605Smrg 1131848b8605Smrg 1132848b8605Smrg 1133848b8605SmrgXMesaBuffer 1134848b8605SmrgXMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap, 1135848b8605Smrg unsigned int width, unsigned int height) 1136848b8605Smrg{ 1137848b8605Smrg XMesaWindow root; 1138848b8605Smrg XMesaDrawable drawable; /* X Pixmap Drawable */ 1139848b8605Smrg XMesaBuffer b; 1140848b8605Smrg 1141848b8605Smrg /* allocate pixmap for front buffer */ 1142848b8605Smrg root = RootWindow( v->display, v->visinfo->screen ); 1143848b8605Smrg drawable = XCreatePixmap(v->display, root, width, height, 1144848b8605Smrg v->visinfo->depth); 1145848b8605Smrg if (!drawable) 1146848b8605Smrg return NULL; 1147848b8605Smrg 1148848b8605Smrg b = create_xmesa_buffer(drawable, PBUFFER, v, cmap); 1149848b8605Smrg if (!b) 1150848b8605Smrg return NULL; 1151848b8605Smrg 1152848b8605Smrg if (!initialize_visual_and_buffer(v, b, drawable, cmap)) { 1153848b8605Smrg xmesa_free_buffer(b); 1154848b8605Smrg return NULL; 1155848b8605Smrg } 1156848b8605Smrg 1157848b8605Smrg return b; 1158848b8605Smrg} 1159848b8605Smrg 1160848b8605Smrg 1161848b8605Smrg 1162848b8605Smrg/* 1163848b8605Smrg * Deallocate an XMesaBuffer structure and all related info. 1164848b8605Smrg */ 1165848b8605SmrgPUBLIC void 1166848b8605SmrgXMesaDestroyBuffer(XMesaBuffer b) 1167848b8605Smrg{ 1168848b8605Smrg xmesa_free_buffer(b); 1169848b8605Smrg} 1170848b8605Smrg 1171848b8605Smrg 1172848b8605Smrg/** 1173848b8605Smrg * Query the current window size and update the corresponding struct gl_framebuffer 1174848b8605Smrg * and all attached renderbuffers. 1175848b8605Smrg * Called when: 1176848b8605Smrg * 1. the first time a buffer is bound to a context. 1177848b8605Smrg * 2. from glViewport to poll for window size changes 1178848b8605Smrg * 3. from the XMesaResizeBuffers() API function. 1179848b8605Smrg * Note: it's possible (and legal) for xmctx to be NULL. That can happen 1180848b8605Smrg * when resizing a buffer when no rendering context is bound. 1181848b8605Smrg */ 1182848b8605Smrgvoid 1183848b8605Smrgxmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) 1184848b8605Smrg{ 1185848b8605Smrg GLuint width, height; 1186848b8605Smrg xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height); 1187848b8605Smrg if (drawBuffer->mesa_buffer.Width != width || 1188848b8605Smrg drawBuffer->mesa_buffer.Height != height) { 1189848b8605Smrg struct gl_context *ctx = xmctx ? &xmctx->mesa : NULL; 1190848b8605Smrg _mesa_resize_framebuffer(ctx, &(drawBuffer->mesa_buffer), width, height); 1191848b8605Smrg } 1192848b8605Smrg} 1193848b8605Smrg 1194848b8605Smrg 1195848b8605Smrg/* 1196848b8605Smrg * Bind buffer b to context c and make c the current rendering context. 1197848b8605Smrg */ 1198848b8605SmrgGLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) 1199848b8605Smrg{ 1200848b8605Smrg return XMesaMakeCurrent2( c, b, b ); 1201848b8605Smrg} 1202848b8605Smrg 1203848b8605Smrg 1204848b8605Smrg/* 1205848b8605Smrg * Bind buffer b to context c and make c the current rendering context. 1206848b8605Smrg */ 1207848b8605SmrgPUBLIC 1208848b8605SmrgGLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, 1209848b8605Smrg XMesaBuffer readBuffer ) 1210848b8605Smrg{ 1211848b8605Smrg if (c) { 1212848b8605Smrg if (!drawBuffer || !readBuffer) 1213848b8605Smrg return GL_FALSE; /* must specify buffers! */ 1214848b8605Smrg 1215848b8605Smrg if (&(c->mesa) == _mesa_get_current_context() 1216848b8605Smrg && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer 1217848b8605Smrg && c->mesa.ReadBuffer == &readBuffer->mesa_buffer 1218848b8605Smrg && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) { 1219848b8605Smrg /* same context and buffer, do nothing */ 1220848b8605Smrg return GL_TRUE; 1221848b8605Smrg } 1222848b8605Smrg 1223848b8605Smrg c->xm_buffer = drawBuffer; 1224848b8605Smrg 1225848b8605Smrg xmesa_check_and_update_buffer_size(c, drawBuffer); 1226848b8605Smrg if (readBuffer != drawBuffer) 1227848b8605Smrg xmesa_check_and_update_buffer_size(c, readBuffer); 1228848b8605Smrg 1229848b8605Smrg _mesa_make_current(&(c->mesa), 1230848b8605Smrg &drawBuffer->mesa_buffer, 1231848b8605Smrg &readBuffer->mesa_buffer); 1232848b8605Smrg 1233848b8605Smrg /* 1234848b8605Smrg * Must recompute and set these pixel values because colormap 1235848b8605Smrg * can be different for different windows. 1236848b8605Smrg */ 1237848b8605Smrg c->clearpixel = xmesa_color_to_pixel( &c->mesa, 1238848b8605Smrg c->clearcolor[0], 1239848b8605Smrg c->clearcolor[1], 1240848b8605Smrg c->clearcolor[2], 1241848b8605Smrg c->clearcolor[3], 1242848b8605Smrg c->xm_visual->undithered_pf); 1243848b8605Smrg XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel); 1244848b8605Smrg 1245848b8605Smrg /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 1246848b8605Smrg drawBuffer->wasCurrent = GL_TRUE; 1247848b8605Smrg } 1248848b8605Smrg else { 1249848b8605Smrg /* Detach */ 1250848b8605Smrg _mesa_make_current( NULL, NULL, NULL ); 1251848b8605Smrg } 1252848b8605Smrg return GL_TRUE; 1253848b8605Smrg} 1254848b8605Smrg 1255848b8605Smrg 1256848b8605Smrg/* 1257848b8605Smrg * Unbind the context c from its buffer. 1258848b8605Smrg */ 1259848b8605SmrgGLboolean XMesaUnbindContext( XMesaContext c ) 1260848b8605Smrg{ 1261848b8605Smrg /* A no-op for XFree86 integration purposes */ 1262848b8605Smrg return GL_TRUE; 1263848b8605Smrg} 1264848b8605Smrg 1265848b8605Smrg 1266848b8605SmrgXMesaContext XMesaGetCurrentContext( void ) 1267848b8605Smrg{ 1268848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1269848b8605Smrg if (ctx) { 1270848b8605Smrg XMesaContext xmesa = XMESA_CONTEXT(ctx); 1271848b8605Smrg return xmesa; 1272848b8605Smrg } 1273848b8605Smrg else { 1274848b8605Smrg return 0; 1275848b8605Smrg } 1276848b8605Smrg} 1277848b8605Smrg 1278848b8605Smrg 1279848b8605SmrgXMesaBuffer XMesaGetCurrentBuffer( void ) 1280848b8605Smrg{ 1281848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1282848b8605Smrg if (ctx) { 1283848b8605Smrg XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); 1284848b8605Smrg return xmbuf; 1285848b8605Smrg } 1286848b8605Smrg else { 1287848b8605Smrg return 0; 1288848b8605Smrg } 1289848b8605Smrg} 1290848b8605Smrg 1291848b8605Smrg 1292848b8605Smrg/* New in Mesa 3.1 */ 1293848b8605SmrgXMesaBuffer XMesaGetCurrentReadBuffer( void ) 1294848b8605Smrg{ 1295848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1296848b8605Smrg if (ctx) { 1297848b8605Smrg return XMESA_BUFFER(ctx->ReadBuffer); 1298848b8605Smrg } 1299848b8605Smrg else { 1300848b8605Smrg return 0; 1301848b8605Smrg } 1302848b8605Smrg} 1303848b8605Smrg 1304848b8605Smrg 1305b8e80941SmrgDisplay *XMesaGetCurrentDisplay(void) 1306848b8605Smrg{ 1307b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1308b8e80941Smrg XMesaContext xmctx = XMESA_CONTEXT(ctx); 1309b8e80941Smrg return xmctx ? xmctx->display : NULL; 1310848b8605Smrg} 1311848b8605Smrg 1312848b8605Smrg 1313848b8605Smrg 1314848b8605Smrg/* 1315848b8605Smrg * Copy the back buffer to the front buffer. If there's no back buffer 1316848b8605Smrg * this is a no-op. 1317848b8605Smrg */ 1318848b8605SmrgPUBLIC 1319848b8605Smrgvoid XMesaSwapBuffers( XMesaBuffer b ) 1320848b8605Smrg{ 1321848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1322848b8605Smrg 1323848b8605Smrg if (!b->backxrb) { 1324848b8605Smrg /* single buffered */ 1325848b8605Smrg return; 1326848b8605Smrg } 1327848b8605Smrg 1328848b8605Smrg /* If we're swapping the buffer associated with the current context 1329848b8605Smrg * we have to flush any pending rendering commands first. 1330848b8605Smrg */ 1331848b8605Smrg if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 1332848b8605Smrg _mesa_notifySwapBuffers(ctx); 1333848b8605Smrg 1334848b8605Smrg if (b->db_mode) { 1335848b8605Smrg if (b->backxrb->ximage) { 1336848b8605Smrg /* Copy Ximage (back buf) from client memory to server window */ 1337848b8605Smrg#if defined(USE_XSHM) 1338848b8605Smrg if (b->shm) { 1339848b8605Smrg /*mtx_lock(&_xmesa_lock);*/ 1340848b8605Smrg XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 1341848b8605Smrg b->swapgc, 1342848b8605Smrg b->backxrb->ximage, 0, 0, 1343848b8605Smrg 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 1344848b8605Smrg False ); 1345848b8605Smrg /*mtx_unlock(&_xmesa_lock);*/ 1346848b8605Smrg } 1347848b8605Smrg else 1348848b8605Smrg#endif 1349848b8605Smrg { 1350848b8605Smrg /*mtx_lock(&_xmesa_lock);*/ 1351848b8605Smrg XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 1352848b8605Smrg b->swapgc, 1353848b8605Smrg b->backxrb->ximage, 0, 0, 1354848b8605Smrg 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height ); 1355848b8605Smrg /*mtx_unlock(&_xmesa_lock);*/ 1356848b8605Smrg } 1357848b8605Smrg } 1358848b8605Smrg else if (b->backxrb->pixmap) { 1359848b8605Smrg /* Copy pixmap (back buf) to window (front buf) on server */ 1360848b8605Smrg /*mtx_lock(&_xmesa_lock);*/ 1361848b8605Smrg XMesaCopyArea( b->xm_visual->display, 1362848b8605Smrg b->backxrb->pixmap, /* source drawable */ 1363848b8605Smrg b->frontxrb->drawable, /* dest. drawable */ 1364848b8605Smrg b->swapgc, 1365848b8605Smrg 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 1366848b8605Smrg 0, 0 /* dest region */ 1367848b8605Smrg ); 1368848b8605Smrg /*mtx_unlock(&_xmesa_lock);*/ 1369848b8605Smrg } 1370848b8605Smrg } 1371848b8605Smrg XSync( b->xm_visual->display, False ); 1372848b8605Smrg} 1373848b8605Smrg 1374848b8605Smrg 1375848b8605Smrg 1376848b8605Smrg/* 1377848b8605Smrg * Copy sub-region of back buffer to front buffer 1378848b8605Smrg */ 1379848b8605Smrgvoid XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) 1380848b8605Smrg{ 1381848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1382848b8605Smrg 1383848b8605Smrg /* If we're swapping the buffer associated with the current context 1384848b8605Smrg * we have to flush any pending rendering commands first. 1385848b8605Smrg */ 1386848b8605Smrg if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) 1387848b8605Smrg _mesa_notifySwapBuffers(ctx); 1388848b8605Smrg 1389848b8605Smrg if (!b->backxrb) { 1390848b8605Smrg /* single buffered */ 1391848b8605Smrg return; 1392848b8605Smrg } 1393848b8605Smrg 1394848b8605Smrg if (b->db_mode) { 1395848b8605Smrg int yTop = b->mesa_buffer.Height - y - height; 1396848b8605Smrg if (b->backxrb->ximage) { 1397848b8605Smrg /* Copy Ximage from host's memory to server's window */ 1398848b8605Smrg#if defined(USE_XSHM) 1399848b8605Smrg if (b->shm) { 1400848b8605Smrg /* XXX assuming width and height aren't too large! */ 1401848b8605Smrg XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, 1402848b8605Smrg b->swapgc, 1403848b8605Smrg b->backxrb->ximage, x, yTop, 1404848b8605Smrg x, yTop, width, height, False ); 1405848b8605Smrg /* wait for finished event??? */ 1406848b8605Smrg } 1407848b8605Smrg else 1408848b8605Smrg#endif 1409848b8605Smrg { 1410848b8605Smrg /* XXX assuming width and height aren't too large! */ 1411848b8605Smrg XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, 1412848b8605Smrg b->swapgc, 1413848b8605Smrg b->backxrb->ximage, x, yTop, 1414848b8605Smrg x, yTop, width, height ); 1415848b8605Smrg } 1416848b8605Smrg } 1417848b8605Smrg else { 1418848b8605Smrg /* Copy pixmap to window on server */ 1419848b8605Smrg XMesaCopyArea( b->xm_visual->display, 1420848b8605Smrg b->backxrb->pixmap, /* source drawable */ 1421848b8605Smrg b->frontxrb->drawable, /* dest. drawable */ 1422848b8605Smrg b->swapgc, 1423848b8605Smrg x, yTop, width, height, /* source region */ 1424848b8605Smrg x, yTop /* dest region */ 1425848b8605Smrg ); 1426848b8605Smrg } 1427848b8605Smrg } 1428848b8605Smrg} 1429848b8605Smrg 1430848b8605Smrg 1431848b8605Smrg/* 1432848b8605Smrg * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function 1433848b8605Smrg * is a way to get "under the hood" of X/Mesa so one can manipulate the 1434848b8605Smrg * back buffer directly. 1435848b8605Smrg * Output: pixmap - pointer to back buffer's Pixmap, or 0 1436848b8605Smrg * ximage - pointer to back buffer's XImage, or NULL 1437848b8605Smrg * Return: GL_TRUE = context is double buffered 1438848b8605Smrg * GL_FALSE = context is single buffered 1439848b8605Smrg */ 1440848b8605SmrgGLboolean XMesaGetBackBuffer( XMesaBuffer b, 1441848b8605Smrg XMesaPixmap *pixmap, 1442848b8605Smrg XMesaImage **ximage ) 1443848b8605Smrg{ 1444848b8605Smrg if (b->db_mode) { 1445848b8605Smrg if (pixmap) 1446848b8605Smrg *pixmap = b->backxrb->pixmap; 1447848b8605Smrg if (ximage) 1448848b8605Smrg *ximage = b->backxrb->ximage; 1449848b8605Smrg return GL_TRUE; 1450848b8605Smrg } 1451848b8605Smrg else { 1452848b8605Smrg *pixmap = 0; 1453848b8605Smrg *ximage = NULL; 1454848b8605Smrg return GL_FALSE; 1455848b8605Smrg } 1456848b8605Smrg} 1457848b8605Smrg 1458848b8605Smrg 1459848b8605Smrg/* 1460848b8605Smrg * Return the depth buffer associated with an XMesaBuffer. 1461848b8605Smrg * Input: b - the XMesa buffer handle 1462848b8605Smrg * Output: width, height - size of buffer in pixels 1463848b8605Smrg * bytesPerValue - bytes per depth value (2 or 4) 1464848b8605Smrg * buffer - pointer to depth buffer values 1465848b8605Smrg * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1466848b8605Smrg */ 1467848b8605SmrgGLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, 1468848b8605Smrg GLint *bytesPerValue, void **buffer ) 1469848b8605Smrg{ 1470848b8605Smrg struct gl_renderbuffer *rb 1471848b8605Smrg = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer; 1472848b8605Smrg struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); 1473848b8605Smrg 1474848b8605Smrg if (!xrb || !xrb->Base.Buffer) { 1475848b8605Smrg *width = 0; 1476848b8605Smrg *height = 0; 1477848b8605Smrg *bytesPerValue = 0; 1478848b8605Smrg *buffer = 0; 1479848b8605Smrg return GL_FALSE; 1480848b8605Smrg } 1481848b8605Smrg else { 1482848b8605Smrg *width = b->mesa_buffer.Width; 1483848b8605Smrg *height = b->mesa_buffer.Height; 1484848b8605Smrg *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16 1485848b8605Smrg ? sizeof(GLushort) : sizeof(GLuint); 1486848b8605Smrg *buffer = (void *) xrb->Base.Buffer; 1487848b8605Smrg return GL_TRUE; 1488848b8605Smrg } 1489848b8605Smrg} 1490848b8605Smrg 1491848b8605Smrg 1492848b8605Smrgvoid XMesaFlush( XMesaContext c ) 1493848b8605Smrg{ 1494848b8605Smrg if (c && c->xm_visual) { 1495848b8605Smrg XSync( c->xm_visual->display, False ); 1496848b8605Smrg } 1497848b8605Smrg} 1498848b8605Smrg 1499848b8605Smrg 1500848b8605Smrg 1501848b8605Smrgconst char *XMesaGetString( XMesaContext c, int name ) 1502848b8605Smrg{ 1503848b8605Smrg (void) c; 1504848b8605Smrg if (name==XMESA_VERSION) { 1505848b8605Smrg return "5.0"; 1506848b8605Smrg } 1507848b8605Smrg else if (name==XMESA_EXTENSIONS) { 1508848b8605Smrg return ""; 1509848b8605Smrg } 1510848b8605Smrg else { 1511848b8605Smrg return NULL; 1512848b8605Smrg } 1513848b8605Smrg} 1514848b8605Smrg 1515848b8605Smrg 1516848b8605Smrg 1517848b8605SmrgXMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) 1518848b8605Smrg{ 1519848b8605Smrg XMesaBuffer b; 1520848b8605Smrg for (b=XMesaBufferList; b; b=b->Next) { 1521848b8605Smrg if (b->frontxrb->drawable == d && b->display == dpy) { 1522848b8605Smrg return b; 1523848b8605Smrg } 1524848b8605Smrg } 1525848b8605Smrg return NULL; 1526848b8605Smrg} 1527848b8605Smrg 1528848b8605Smrg 1529848b8605Smrg/** 1530848b8605Smrg * Free/destroy all XMesaBuffers associated with given display. 1531848b8605Smrg */ 1532848b8605Smrgvoid xmesa_destroy_buffers_on_display(XMesaDisplay *dpy) 1533848b8605Smrg{ 1534848b8605Smrg XMesaBuffer b, next; 1535848b8605Smrg for (b = XMesaBufferList; b; b = next) { 1536848b8605Smrg next = b->Next; 1537848b8605Smrg if (b->display == dpy) { 1538848b8605Smrg xmesa_free_buffer(b); 1539848b8605Smrg } 1540848b8605Smrg } 1541848b8605Smrg} 1542848b8605Smrg 1543848b8605Smrg 1544848b8605Smrg/* 1545848b8605Smrg * Look for XMesaBuffers whose X window has been destroyed. 1546848b8605Smrg * Deallocate any such XMesaBuffers. 1547848b8605Smrg */ 1548848b8605Smrgvoid XMesaGarbageCollect( XMesaDisplay* dpy ) 1549848b8605Smrg{ 1550848b8605Smrg XMesaBuffer b, next; 1551848b8605Smrg for (b=XMesaBufferList; b; b=next) { 1552848b8605Smrg next = b->Next; 1553848b8605Smrg if (b->display && b->display == dpy && b->frontxrb->drawable && b->type == WINDOW) { 1554848b8605Smrg XSync(b->display, False); 1555848b8605Smrg if (!window_exists( b->display, b->frontxrb->drawable )) { 1556848b8605Smrg /* found a dead window, free the ancillary info */ 1557848b8605Smrg XMesaDestroyBuffer( b ); 1558848b8605Smrg } 1559848b8605Smrg } 1560848b8605Smrg } 1561848b8605Smrg} 1562848b8605Smrg 1563848b8605Smrg 1564848b8605Smrgunsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, 1565848b8605Smrg GLfloat red, GLfloat green, 1566848b8605Smrg GLfloat blue, GLfloat alpha ) 1567848b8605Smrg{ 1568848b8605Smrg GLint r = (GLint) (red * 255.0F); 1569848b8605Smrg GLint g = (GLint) (green * 255.0F); 1570848b8605Smrg GLint b = (GLint) (blue * 255.0F); 1571848b8605Smrg GLint a = (GLint) (alpha * 255.0F); 1572848b8605Smrg 1573848b8605Smrg switch (xmesa->pixelformat) { 1574848b8605Smrg case PF_Truecolor: 1575848b8605Smrg { 1576848b8605Smrg unsigned long p; 1577848b8605Smrg PACK_TRUECOLOR( p, r, g, b ); 1578848b8605Smrg return p; 1579848b8605Smrg } 1580848b8605Smrg case PF_8A8B8G8R: 1581848b8605Smrg return PACK_8A8B8G8R( r, g, b, a ); 1582848b8605Smrg case PF_8A8R8G8B: 1583848b8605Smrg return PACK_8A8R8G8B( r, g, b, a ); 1584848b8605Smrg case PF_8R8G8B: 1585848b8605Smrg return PACK_8R8G8B( r, g, b ); 1586848b8605Smrg case PF_5R6G5B: 1587848b8605Smrg return PACK_5R6G5B( r, g, b ); 1588848b8605Smrg case PF_Dither_5R6G5B: 1589848b8605Smrg /* fall through */ 1590848b8605Smrg case PF_Dither_True: 1591848b8605Smrg { 1592848b8605Smrg unsigned long p; 1593848b8605Smrg PACK_TRUEDITHER(p, x, y, r, g, b); 1594848b8605Smrg return p; 1595848b8605Smrg } 1596848b8605Smrg default: 1597848b8605Smrg _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); 1598848b8605Smrg } 1599848b8605Smrg return 0; 1600848b8605Smrg} 1601848b8605Smrg 1602848b8605Smrg 1603848b8605Smrg/* 1604848b8605Smrg * This is typically called when the window size changes and we need 1605848b8605Smrg * to reallocate the buffer's back/depth/stencil/accum buffers. 1606848b8605Smrg */ 1607848b8605SmrgPUBLIC void 1608848b8605SmrgXMesaResizeBuffers( XMesaBuffer b ) 1609848b8605Smrg{ 1610848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1611848b8605Smrg XMesaContext xmctx = XMESA_CONTEXT(ctx); 1612848b8605Smrg if (!xmctx) 1613848b8605Smrg return; 1614848b8605Smrg xmesa_check_and_update_buffer_size(xmctx, b); 1615848b8605Smrg} 1616848b8605Smrg 1617848b8605Smrg 1618848b8605Smrgstatic GLint 1619848b8605Smrgxbuffer_to_renderbuffer(int buffer) 1620848b8605Smrg{ 1621848b8605Smrg assert(MAX_AUX_BUFFERS <= 4); 1622848b8605Smrg 1623848b8605Smrg switch (buffer) { 1624848b8605Smrg case GLX_FRONT_LEFT_EXT: 1625848b8605Smrg return BUFFER_FRONT_LEFT; 1626848b8605Smrg case GLX_FRONT_RIGHT_EXT: 1627848b8605Smrg return BUFFER_FRONT_RIGHT; 1628848b8605Smrg case GLX_BACK_LEFT_EXT: 1629848b8605Smrg return BUFFER_BACK_LEFT; 1630848b8605Smrg case GLX_BACK_RIGHT_EXT: 1631848b8605Smrg return BUFFER_BACK_RIGHT; 1632848b8605Smrg case GLX_AUX0_EXT: 1633848b8605Smrg return BUFFER_AUX0; 1634848b8605Smrg case GLX_AUX1_EXT: 1635848b8605Smrg case GLX_AUX2_EXT: 1636848b8605Smrg case GLX_AUX3_EXT: 1637848b8605Smrg case GLX_AUX4_EXT: 1638848b8605Smrg case GLX_AUX5_EXT: 1639848b8605Smrg case GLX_AUX6_EXT: 1640848b8605Smrg case GLX_AUX7_EXT: 1641848b8605Smrg case GLX_AUX8_EXT: 1642848b8605Smrg case GLX_AUX9_EXT: 1643848b8605Smrg default: 1644848b8605Smrg /* BadValue error */ 1645848b8605Smrg return -1; 1646848b8605Smrg } 1647848b8605Smrg} 1648848b8605Smrg 1649848b8605Smrg 1650848b8605SmrgPUBLIC void 1651848b8605SmrgXMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer, 1652848b8605Smrg const int *attrib_list) 1653848b8605Smrg{ 1654848b8605Smrg#if 0 1655848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1656848b8605Smrg const GLuint unit = ctx->Texture.CurrentUnit; 1657848b8605Smrg struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 1658848b8605Smrg struct gl_texture_object *texObj; 1659848b8605Smrg#endif 1660848b8605Smrg struct gl_renderbuffer *rb; 1661848b8605Smrg struct xmesa_renderbuffer *xrb; 1662848b8605Smrg GLint b; 1663848b8605Smrg XMesaImage *img = NULL; 1664848b8605Smrg GLboolean freeImg = GL_FALSE; 1665848b8605Smrg 1666848b8605Smrg b = xbuffer_to_renderbuffer(buffer); 1667848b8605Smrg if (b < 0) 1668848b8605Smrg return; 1669848b8605Smrg 1670848b8605Smrg if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT) 1671848b8605Smrg return; /* BadMatch error */ 1672848b8605Smrg 1673848b8605Smrg rb = drawable->mesa_buffer.Attachment[b].Renderbuffer; 1674848b8605Smrg if (!rb) { 1675848b8605Smrg /* invalid buffer */ 1676848b8605Smrg return; 1677848b8605Smrg } 1678848b8605Smrg xrb = xmesa_renderbuffer(rb); 1679848b8605Smrg 1680848b8605Smrg#if 0 1681848b8605Smrg switch (drawable->TextureTarget) { 1682848b8605Smrg case GLX_TEXTURE_1D_EXT: 1683848b8605Smrg texObj = texUnit->CurrentTex[TEXTURE_1D_INDEX]; 1684848b8605Smrg break; 1685848b8605Smrg case GLX_TEXTURE_2D_EXT: 1686848b8605Smrg texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX]; 1687848b8605Smrg break; 1688848b8605Smrg case GLX_TEXTURE_RECTANGLE_EXT: 1689848b8605Smrg texObj = texUnit->CurrentTex[TEXTURE_RECT_INDEX]; 1690848b8605Smrg break; 1691848b8605Smrg default: 1692848b8605Smrg return; /* BadMatch error */ 1693848b8605Smrg } 1694848b8605Smrg#endif 1695848b8605Smrg 1696848b8605Smrg /* 1697848b8605Smrg * The following is a quick and simple way to implement 1698848b8605Smrg * BindTexImage. The better way is to write some new FetchTexel() 1699848b8605Smrg * functions which would extract texels from XImages. We'd still 1700848b8605Smrg * need to use GetImage when texturing from a Pixmap (front buffer) 1701848b8605Smrg * but texturing from a back buffer (XImage) would avoid an image 1702848b8605Smrg * copy. 1703848b8605Smrg */ 1704848b8605Smrg 1705848b8605Smrg /* get XImage */ 1706848b8605Smrg if (xrb->pixmap) { 1707848b8605Smrg img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L, 1708848b8605Smrg ZPixmap); 1709848b8605Smrg freeImg = GL_TRUE; 1710848b8605Smrg } 1711848b8605Smrg else if (xrb->ximage) { 1712848b8605Smrg img = xrb->ximage; 1713848b8605Smrg } 1714848b8605Smrg 1715848b8605Smrg /* store the XImage as a new texture image */ 1716848b8605Smrg if (img) { 1717848b8605Smrg GLenum format, type, intFormat; 1718848b8605Smrg if (img->bits_per_pixel == 32) { 1719848b8605Smrg format = GL_BGRA; 1720848b8605Smrg type = GL_UNSIGNED_BYTE; 1721848b8605Smrg intFormat = GL_RGBA; 1722848b8605Smrg } 1723848b8605Smrg else if (img->bits_per_pixel == 24) { 1724848b8605Smrg format = GL_BGR; 1725848b8605Smrg type = GL_UNSIGNED_BYTE; 1726848b8605Smrg intFormat = GL_RGB; 1727848b8605Smrg } 1728848b8605Smrg else if (img->bits_per_pixel == 16) { 1729848b8605Smrg format = GL_BGR; 1730848b8605Smrg type = GL_UNSIGNED_SHORT_5_6_5; 1731848b8605Smrg intFormat = GL_RGB; 1732848b8605Smrg } 1733848b8605Smrg else { 1734848b8605Smrg _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage"); 1735848b8605Smrg return; 1736848b8605Smrg } 1737848b8605Smrg if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) { 1738848b8605Smrg intFormat = GL_RGBA; 1739848b8605Smrg } 1740848b8605Smrg else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) { 1741848b8605Smrg intFormat = GL_RGB; 1742848b8605Smrg } 1743848b8605Smrg 1744848b8605Smrg _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0, 1745848b8605Smrg format, type, img->data); 1746848b8605Smrg 1747848b8605Smrg if (freeImg) { 1748848b8605Smrg XMesaDestroyImage(img); 1749848b8605Smrg } 1750848b8605Smrg } 1751848b8605Smrg} 1752848b8605Smrg 1753848b8605Smrg 1754848b8605Smrg 1755848b8605SmrgPUBLIC void 1756848b8605SmrgXMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer) 1757848b8605Smrg{ 1758848b8605Smrg const GLint b = xbuffer_to_renderbuffer(buffer); 1759848b8605Smrg if (b < 0) 1760848b8605Smrg return; 1761848b8605Smrg 1762848b8605Smrg /* no-op for now */ 1763848b8605Smrg} 1764848b8605Smrg 1765