1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci/** 26bf215546Sopenharmony_ci * \file xm_api.c 27bf215546Sopenharmony_ci * 28bf215546Sopenharmony_ci * All the XMesa* API functions. 29bf215546Sopenharmony_ci * 30bf215546Sopenharmony_ci * 31bf215546Sopenharmony_ci * NOTES: 32bf215546Sopenharmony_ci * 33bf215546Sopenharmony_ci * The window coordinate system origin (0,0) is in the lower-left corner 34bf215546Sopenharmony_ci * of the window. X11's window coordinate origin is in the upper-left 35bf215546Sopenharmony_ci * corner of the window. Therefore, most drawing functions in this 36bf215546Sopenharmony_ci * file have to flip Y coordinates. 37bf215546Sopenharmony_ci * 38bf215546Sopenharmony_ci * 39bf215546Sopenharmony_ci * Byte swapping: If the Mesa host and the X display use a different 40bf215546Sopenharmony_ci * byte order then there's some trickiness to be aware of when using 41bf215546Sopenharmony_ci * XImages. The byte ordering used for the XImage is that of the X 42bf215546Sopenharmony_ci * display, not the Mesa host. 43bf215546Sopenharmony_ci * The color-to-pixel encoding for True/DirectColor must be done 44bf215546Sopenharmony_ci * according to the display's visual red_mask, green_mask, and blue_mask. 45bf215546Sopenharmony_ci * If XPutPixel is used to put a pixel into an XImage then XPutPixel will 46bf215546Sopenharmony_ci * do byte swapping if needed. If one wants to directly "poke" the pixel 47bf215546Sopenharmony_ci * into the XImage's buffer then the pixel must be byte swapped first. 48bf215546Sopenharmony_ci * 49bf215546Sopenharmony_ci */ 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci#ifdef __CYGWIN__ 52bf215546Sopenharmony_ci#undef WIN32 53bf215546Sopenharmony_ci#undef __WIN32__ 54bf215546Sopenharmony_ci#endif 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci#include <stdio.h> 57bf215546Sopenharmony_ci#include "xm_api.h" 58bf215546Sopenharmony_ci#include "xm_st.h" 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci#include "pipe/p_context.h" 61bf215546Sopenharmony_ci#include "pipe/p_defines.h" 62bf215546Sopenharmony_ci#include "pipe/p_screen.h" 63bf215546Sopenharmony_ci#include "pipe/p_state.h" 64bf215546Sopenharmony_ci#include "frontend/api.h" 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci#include "util/u_atomic.h" 67bf215546Sopenharmony_ci#include "util/u_inlines.h" 68bf215546Sopenharmony_ci#include "util/u_math.h" 69bf215546Sopenharmony_ci#include "util/u_memory.h" 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci#include "hud/hud_context.h" 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci#include "main/errors.h" 74bf215546Sopenharmony_ci#include "main/mtypes.h" 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci#include "xm_public.h" 77bf215546Sopenharmony_ci#include <GL/glx.h> 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci/* Driver interface routines, set up by xlib backend on library 81bf215546Sopenharmony_ci * _init(). These are global in the same way that function names are 82bf215546Sopenharmony_ci * global. 83bf215546Sopenharmony_ci */ 84bf215546Sopenharmony_cistatic struct xm_driver driver; 85bf215546Sopenharmony_cistatic struct st_api *stapi; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci/* Default strict invalidate to false. This means we will not call 88bf215546Sopenharmony_ci * XGetGeometry after every swapbuffers, which allows swapbuffers to 89bf215546Sopenharmony_ci * remain asynchronous. For apps running at 100fps with synchronous 90bf215546Sopenharmony_ci * swapping, a 10% boost is typical. For gears, I see closer to 20% 91bf215546Sopenharmony_ci * speedup. 92bf215546Sopenharmony_ci * 93bf215546Sopenharmony_ci * Note that the work of copying data on swapbuffers doesn't disappear 94bf215546Sopenharmony_ci * - this change just allows the X server to execute the PutImage 95bf215546Sopenharmony_ci * asynchronously without us effectively blocked until its completion. 96bf215546Sopenharmony_ci * 97bf215546Sopenharmony_ci * This speeds up even llvmpipe's threaded rasterization as the 98bf215546Sopenharmony_ci * swapbuffers operation was a large part of the serial component of 99bf215546Sopenharmony_ci * an llvmpipe frame. 100bf215546Sopenharmony_ci * 101bf215546Sopenharmony_ci * The downside of this is correctness - applications which don't call 102bf215546Sopenharmony_ci * glViewport on window resizes will get incorrect rendering. A 103bf215546Sopenharmony_ci * better solution would be to have per-frame but asynchronous 104bf215546Sopenharmony_ci * invalidation. Xcb almost looks as if it could provide this, but 105bf215546Sopenharmony_ci * the API doesn't seem to quite be there. 106bf215546Sopenharmony_ci */ 107bf215546Sopenharmony_ciboolean xmesa_strict_invalidate = FALSE; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_civoid xmesa_set_driver( const struct xm_driver *templ ) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci driver = *templ; 112bf215546Sopenharmony_ci stapi = driver.create_st_api(); 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci xmesa_strict_invalidate = 115bf215546Sopenharmony_ci debug_get_bool_option("XMESA_STRICT_INVALIDATE", FALSE); 116bf215546Sopenharmony_ci} 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_cistatic int 120bf215546Sopenharmony_cixmesa_get_param(struct st_manager *smapi, 121bf215546Sopenharmony_ci enum st_manager_param param) 122bf215546Sopenharmony_ci{ 123bf215546Sopenharmony_ci switch(param) { 124bf215546Sopenharmony_ci case ST_MANAGER_BROKEN_INVALIDATE: 125bf215546Sopenharmony_ci return !xmesa_strict_invalidate; 126bf215546Sopenharmony_ci default: 127bf215546Sopenharmony_ci return 0; 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci} 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci/* linked list of XMesaDisplay hooks per display */ 132bf215546Sopenharmony_citypedef struct _XMesaExtDisplayInfo { 133bf215546Sopenharmony_ci struct _XMesaExtDisplayInfo *next; 134bf215546Sopenharmony_ci Display *display; 135bf215546Sopenharmony_ci struct xmesa_display mesaDisplay; 136bf215546Sopenharmony_ci} XMesaExtDisplayInfo; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_citypedef struct _XMesaExtInfo { 139bf215546Sopenharmony_ci XMesaExtDisplayInfo *head; 140bf215546Sopenharmony_ci int ndisplays; 141bf215546Sopenharmony_ci} XMesaExtInfo; 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_cistatic XMesaExtInfo MesaExtInfo; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci/* hook to delete XMesaDisplay on XDestroyDisplay */ 146bf215546Sopenharmony_ciextern void 147bf215546Sopenharmony_cixmesa_close_display(Display *display) 148bf215546Sopenharmony_ci{ 149bf215546Sopenharmony_ci XMesaExtDisplayInfo *info, *prev; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci /* These assertions are not valid since screen creation can fail and result 152bf215546Sopenharmony_ci * in an empty list 153bf215546Sopenharmony_ci assert(MesaExtInfo.ndisplays > 0); 154bf215546Sopenharmony_ci assert(MesaExtInfo.head); 155bf215546Sopenharmony_ci */ 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci _XLockMutex(_Xglobal_lock); 158bf215546Sopenharmony_ci /* first find display */ 159bf215546Sopenharmony_ci prev = NULL; 160bf215546Sopenharmony_ci for (info = MesaExtInfo.head; info; info = info->next) { 161bf215546Sopenharmony_ci if (info->display == display) { 162bf215546Sopenharmony_ci prev = info; 163bf215546Sopenharmony_ci break; 164bf215546Sopenharmony_ci } 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci if (info == NULL) { 168bf215546Sopenharmony_ci /* no display found */ 169bf215546Sopenharmony_ci _XUnlockMutex(_Xglobal_lock); 170bf215546Sopenharmony_ci return; 171bf215546Sopenharmony_ci } 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci /* remove display entry from list */ 174bf215546Sopenharmony_ci if (prev != MesaExtInfo.head) { 175bf215546Sopenharmony_ci prev->next = info->next; 176bf215546Sopenharmony_ci } else { 177bf215546Sopenharmony_ci MesaExtInfo.head = info->next; 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci MesaExtInfo.ndisplays--; 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci _XUnlockMutex(_Xglobal_lock); 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci /* don't forget to clean up mesaDisplay */ 184bf215546Sopenharmony_ci XMesaDisplay xmdpy = &info->mesaDisplay; 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci /** 187bf215546Sopenharmony_ci * XXX: Don't destroy the screens here, since there may still 188bf215546Sopenharmony_ci * be some dangling screen pointers that are used after this point 189bf215546Sopenharmony_ci * if (xmdpy->screen) { 190bf215546Sopenharmony_ci * xmdpy->screen->destroy(xmdpy->screen); 191bf215546Sopenharmony_ci * } 192bf215546Sopenharmony_ci */ 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci if (xmdpy->smapi->destroy) 195bf215546Sopenharmony_ci xmdpy->smapi->destroy(xmdpy->smapi); 196bf215546Sopenharmony_ci free(xmdpy->smapi); 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci XFree((char *) info); 199bf215546Sopenharmony_ci} 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_cistatic XMesaDisplay 202bf215546Sopenharmony_cixmesa_init_display( Display *display ) 203bf215546Sopenharmony_ci{ 204bf215546Sopenharmony_ci static mtx_t init_mutex = _MTX_INITIALIZER_NP; 205bf215546Sopenharmony_ci XMesaDisplay xmdpy; 206bf215546Sopenharmony_ci XMesaExtDisplayInfo *info; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci if (display == NULL) { 209bf215546Sopenharmony_ci return NULL; 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci mtx_lock(&init_mutex); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci /* Look for XMesaDisplay which corresponds to this display */ 215bf215546Sopenharmony_ci info = MesaExtInfo.head; 216bf215546Sopenharmony_ci while(info) { 217bf215546Sopenharmony_ci if (info->display == display) { 218bf215546Sopenharmony_ci /* Found it */ 219bf215546Sopenharmony_ci mtx_unlock(&init_mutex); 220bf215546Sopenharmony_ci return &info->mesaDisplay; 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci info = info->next; 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci /* Not found. Create new XMesaDisplay */ 226bf215546Sopenharmony_ci /* first allocate X-related resources and hook destroy callback */ 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci /* allocate mesa display info */ 229bf215546Sopenharmony_ci info = (XMesaExtDisplayInfo *) Xmalloc(sizeof(XMesaExtDisplayInfo)); 230bf215546Sopenharmony_ci if (info == NULL) { 231bf215546Sopenharmony_ci mtx_unlock(&init_mutex); 232bf215546Sopenharmony_ci return NULL; 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci info->display = display; 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci xmdpy = &info->mesaDisplay; /* to be filled out below */ 237bf215546Sopenharmony_ci xmdpy->display = display; 238bf215546Sopenharmony_ci xmdpy->pipe = NULL; 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci xmdpy->smapi = CALLOC_STRUCT(st_manager); 241bf215546Sopenharmony_ci if (!xmdpy->smapi) { 242bf215546Sopenharmony_ci Xfree(info); 243bf215546Sopenharmony_ci mtx_unlock(&init_mutex); 244bf215546Sopenharmony_ci return NULL; 245bf215546Sopenharmony_ci } 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci xmdpy->screen = driver.create_pipe_screen(display); 248bf215546Sopenharmony_ci if (!xmdpy->screen) { 249bf215546Sopenharmony_ci free(xmdpy->smapi); 250bf215546Sopenharmony_ci Xfree(info); 251bf215546Sopenharmony_ci mtx_unlock(&init_mutex); 252bf215546Sopenharmony_ci return NULL; 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci /* At this point, both smapi and screen are known to be valid */ 256bf215546Sopenharmony_ci xmdpy->smapi->screen = xmdpy->screen; 257bf215546Sopenharmony_ci xmdpy->smapi->get_param = xmesa_get_param; 258bf215546Sopenharmony_ci (void) mtx_init(&xmdpy->mutex, mtx_plain); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci /* chain to the list of displays */ 261bf215546Sopenharmony_ci _XLockMutex(_Xglobal_lock); 262bf215546Sopenharmony_ci info->next = MesaExtInfo.head; 263bf215546Sopenharmony_ci MesaExtInfo.head = info; 264bf215546Sopenharmony_ci MesaExtInfo.ndisplays++; 265bf215546Sopenharmony_ci _XUnlockMutex(_Xglobal_lock); 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci mtx_unlock(&init_mutex); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci return xmdpy; 270bf215546Sopenharmony_ci} 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci/**********************************************************************/ 274bf215546Sopenharmony_ci/***** X Utility Functions *****/ 275bf215546Sopenharmony_ci/**********************************************************************/ 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci/** 279bf215546Sopenharmony_ci * Return the host's byte order as LSBFirst or MSBFirst ala X. 280bf215546Sopenharmony_ci */ 281bf215546Sopenharmony_cistatic int host_byte_order( void ) 282bf215546Sopenharmony_ci{ 283bf215546Sopenharmony_ci int i = 1; 284bf215546Sopenharmony_ci char *cptr = (char *) &i; 285bf215546Sopenharmony_ci return (*cptr==1) ? LSBFirst : MSBFirst; 286bf215546Sopenharmony_ci} 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci/** 292bf215546Sopenharmony_ci * Return the true number of bits per pixel for XImages. 293bf215546Sopenharmony_ci * For example, if we request a 24-bit deep visual we may actually need/get 294bf215546Sopenharmony_ci * 32bpp XImages. This function returns the appropriate bpp. 295bf215546Sopenharmony_ci * Input: dpy - the X display 296bf215546Sopenharmony_ci * visinfo - desribes the visual to be used for XImages 297bf215546Sopenharmony_ci * Return: true number of bits per pixel for XImages 298bf215546Sopenharmony_ci */ 299bf215546Sopenharmony_cistatic int 300bf215546Sopenharmony_cibits_per_pixel( XMesaVisual xmv ) 301bf215546Sopenharmony_ci{ 302bf215546Sopenharmony_ci Display *dpy = xmv->display; 303bf215546Sopenharmony_ci XVisualInfo * visinfo = xmv->visinfo; 304bf215546Sopenharmony_ci XImage *img; 305bf215546Sopenharmony_ci int bitsPerPixel; 306bf215546Sopenharmony_ci /* Create a temporary XImage */ 307bf215546Sopenharmony_ci img = XCreateImage( dpy, visinfo->visual, visinfo->depth, 308bf215546Sopenharmony_ci ZPixmap, 0, /*format, offset*/ 309bf215546Sopenharmony_ci malloc(8), /*data*/ 310bf215546Sopenharmony_ci 1, 1, /*width, height*/ 311bf215546Sopenharmony_ci 32, /*bitmap_pad*/ 312bf215546Sopenharmony_ci 0 /*bytes_per_line*/ 313bf215546Sopenharmony_ci ); 314bf215546Sopenharmony_ci assert(img); 315bf215546Sopenharmony_ci /* grab the bits/pixel value */ 316bf215546Sopenharmony_ci bitsPerPixel = img->bits_per_pixel; 317bf215546Sopenharmony_ci /* free the XImage */ 318bf215546Sopenharmony_ci free( img->data ); 319bf215546Sopenharmony_ci img->data = NULL; 320bf215546Sopenharmony_ci XDestroyImage( img ); 321bf215546Sopenharmony_ci return bitsPerPixel; 322bf215546Sopenharmony_ci} 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci/* 327bf215546Sopenharmony_ci * Determine if a given X window ID is valid (window exists). 328bf215546Sopenharmony_ci * Do this by calling XGetWindowAttributes() for the window and 329bf215546Sopenharmony_ci * checking if we catch an X error. 330bf215546Sopenharmony_ci * Input: dpy - the display 331bf215546Sopenharmony_ci * win - the window to check for existence 332bf215546Sopenharmony_ci * Return: GL_TRUE - window exists 333bf215546Sopenharmony_ci * GL_FALSE - window doesn't exist 334bf215546Sopenharmony_ci */ 335bf215546Sopenharmony_cistatic GLboolean WindowExistsFlag; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_cistatic int window_exists_err_handler( Display* dpy, XErrorEvent* xerr ) 338bf215546Sopenharmony_ci{ 339bf215546Sopenharmony_ci (void) dpy; 340bf215546Sopenharmony_ci if (xerr->error_code == BadWindow) { 341bf215546Sopenharmony_ci WindowExistsFlag = GL_FALSE; 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci return 0; 344bf215546Sopenharmony_ci} 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_cistatic GLboolean window_exists( Display *dpy, Window win ) 347bf215546Sopenharmony_ci{ 348bf215546Sopenharmony_ci XWindowAttributes wa; 349bf215546Sopenharmony_ci int (*old_handler)( Display*, XErrorEvent* ); 350bf215546Sopenharmony_ci WindowExistsFlag = GL_TRUE; 351bf215546Sopenharmony_ci old_handler = XSetErrorHandler(window_exists_err_handler); 352bf215546Sopenharmony_ci XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ 353bf215546Sopenharmony_ci XSetErrorHandler(old_handler); 354bf215546Sopenharmony_ci return WindowExistsFlag; 355bf215546Sopenharmony_ci} 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_cistatic Status 358bf215546Sopenharmony_ciget_drawable_size( Display *dpy, Drawable d, uint *width, uint *height ) 359bf215546Sopenharmony_ci{ 360bf215546Sopenharmony_ci Window root; 361bf215546Sopenharmony_ci Status stat; 362bf215546Sopenharmony_ci int xpos, ypos; 363bf215546Sopenharmony_ci unsigned int w, h, bw, depth; 364bf215546Sopenharmony_ci stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); 365bf215546Sopenharmony_ci *width = w; 366bf215546Sopenharmony_ci *height = h; 367bf215546Sopenharmony_ci return stat; 368bf215546Sopenharmony_ci} 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci/** 372bf215546Sopenharmony_ci * Return the size of the window (or pixmap) that corresponds to the 373bf215546Sopenharmony_ci * given XMesaBuffer. 374bf215546Sopenharmony_ci * \param width returns width in pixels 375bf215546Sopenharmony_ci * \param height returns height in pixels 376bf215546Sopenharmony_ci */ 377bf215546Sopenharmony_civoid 378bf215546Sopenharmony_cixmesa_get_window_size(Display *dpy, XMesaBuffer b, 379bf215546Sopenharmony_ci GLuint *width, GLuint *height) 380bf215546Sopenharmony_ci{ 381bf215546Sopenharmony_ci XMesaDisplay xmdpy = xmesa_init_display(dpy); 382bf215546Sopenharmony_ci Status stat; 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_ci mtx_lock(&xmdpy->mutex); 385bf215546Sopenharmony_ci stat = get_drawable_size(dpy, b->ws.drawable, width, height); 386bf215546Sopenharmony_ci mtx_unlock(&xmdpy->mutex); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci if (!stat) { 389bf215546Sopenharmony_ci /* probably querying a window that's recently been destroyed */ 390bf215546Sopenharmony_ci _mesa_warning(NULL, "XGetGeometry failed!\n"); 391bf215546Sopenharmony_ci *width = *height = 1; 392bf215546Sopenharmony_ci } 393bf215546Sopenharmony_ci} 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci#define GET_REDMASK(__v) __v->mesa_visual.redMask 396bf215546Sopenharmony_ci#define GET_GREENMASK(__v) __v->mesa_visual.greenMask 397bf215546Sopenharmony_ci#define GET_BLUEMASK(__v) __v->mesa_visual.blueMask 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci/** 401bf215546Sopenharmony_ci * Choose the pixel format for the given visual. 402bf215546Sopenharmony_ci * This will tell the gallium driver how to pack pixel data into 403bf215546Sopenharmony_ci * drawing surfaces. 404bf215546Sopenharmony_ci */ 405bf215546Sopenharmony_cistatic GLuint 406bf215546Sopenharmony_cichoose_pixel_format(XMesaVisual v) 407bf215546Sopenharmony_ci{ 408bf215546Sopenharmony_ci boolean native_byte_order = (host_byte_order() == 409bf215546Sopenharmony_ci ImageByteOrder(v->display)); 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci if ( GET_REDMASK(v) == 0x0000ff 412bf215546Sopenharmony_ci && GET_GREENMASK(v) == 0x00ff00 413bf215546Sopenharmony_ci && GET_BLUEMASK(v) == 0xff0000 414bf215546Sopenharmony_ci && v->BitsPerPixel == 32) { 415bf215546Sopenharmony_ci if (native_byte_order) { 416bf215546Sopenharmony_ci /* no byteswapping needed */ 417bf215546Sopenharmony_ci return PIPE_FORMAT_RGBA8888_UNORM; 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci else { 420bf215546Sopenharmony_ci return PIPE_FORMAT_ABGR8888_UNORM; 421bf215546Sopenharmony_ci } 422bf215546Sopenharmony_ci } 423bf215546Sopenharmony_ci else if ( GET_REDMASK(v) == 0xff0000 424bf215546Sopenharmony_ci && GET_GREENMASK(v) == 0x00ff00 425bf215546Sopenharmony_ci && GET_BLUEMASK(v) == 0x0000ff 426bf215546Sopenharmony_ci && v->BitsPerPixel == 32) { 427bf215546Sopenharmony_ci if (native_byte_order) { 428bf215546Sopenharmony_ci /* no byteswapping needed */ 429bf215546Sopenharmony_ci return PIPE_FORMAT_BGRA8888_UNORM; 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci else { 432bf215546Sopenharmony_ci return PIPE_FORMAT_ARGB8888_UNORM; 433bf215546Sopenharmony_ci } 434bf215546Sopenharmony_ci } 435bf215546Sopenharmony_ci else if ( GET_REDMASK(v) == 0x0000ff00 436bf215546Sopenharmony_ci && GET_GREENMASK(v) == 0x00ff0000 437bf215546Sopenharmony_ci && GET_BLUEMASK(v) == 0xff000000 438bf215546Sopenharmony_ci && v->BitsPerPixel == 32) { 439bf215546Sopenharmony_ci if (native_byte_order) { 440bf215546Sopenharmony_ci /* no byteswapping needed */ 441bf215546Sopenharmony_ci return PIPE_FORMAT_ARGB8888_UNORM; 442bf215546Sopenharmony_ci } 443bf215546Sopenharmony_ci else { 444bf215546Sopenharmony_ci return PIPE_FORMAT_BGRA8888_UNORM; 445bf215546Sopenharmony_ci } 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci else if ( GET_REDMASK(v) == 0xf800 448bf215546Sopenharmony_ci && GET_GREENMASK(v) == 0x07e0 449bf215546Sopenharmony_ci && GET_BLUEMASK(v) == 0x001f 450bf215546Sopenharmony_ci && native_byte_order 451bf215546Sopenharmony_ci && v->BitsPerPixel == 16) { 452bf215546Sopenharmony_ci /* 5-6-5 RGB */ 453bf215546Sopenharmony_ci return PIPE_FORMAT_B5G6R5_UNORM; 454bf215546Sopenharmony_ci } 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 457bf215546Sopenharmony_ci} 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci/** 461bf215546Sopenharmony_ci * Choose a depth/stencil format that satisfies the given depth and 462bf215546Sopenharmony_ci * stencil sizes. 463bf215546Sopenharmony_ci */ 464bf215546Sopenharmony_cistatic enum pipe_format 465bf215546Sopenharmony_cichoose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil, 466bf215546Sopenharmony_ci int sample_count) 467bf215546Sopenharmony_ci{ 468bf215546Sopenharmony_ci const enum pipe_texture_target target = PIPE_TEXTURE_2D; 469bf215546Sopenharmony_ci const unsigned tex_usage = PIPE_BIND_DEPTH_STENCIL; 470bf215546Sopenharmony_ci enum pipe_format formats[8], fmt; 471bf215546Sopenharmony_ci int count, i; 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci count = 0; 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci if (depth <= 16 && stencil == 0) { 476bf215546Sopenharmony_ci formats[count++] = PIPE_FORMAT_Z16_UNORM; 477bf215546Sopenharmony_ci } 478bf215546Sopenharmony_ci if (depth <= 24 && stencil == 0) { 479bf215546Sopenharmony_ci formats[count++] = PIPE_FORMAT_X8Z24_UNORM; 480bf215546Sopenharmony_ci formats[count++] = PIPE_FORMAT_Z24X8_UNORM; 481bf215546Sopenharmony_ci } 482bf215546Sopenharmony_ci if (depth <= 24 && stencil <= 8) { 483bf215546Sopenharmony_ci formats[count++] = PIPE_FORMAT_S8_UINT_Z24_UNORM; 484bf215546Sopenharmony_ci formats[count++] = PIPE_FORMAT_Z24_UNORM_S8_UINT; 485bf215546Sopenharmony_ci } 486bf215546Sopenharmony_ci if (depth <= 32 && stencil == 0) { 487bf215546Sopenharmony_ci formats[count++] = PIPE_FORMAT_Z32_UNORM; 488bf215546Sopenharmony_ci } 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci fmt = PIPE_FORMAT_NONE; 491bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 492bf215546Sopenharmony_ci if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i], 493bf215546Sopenharmony_ci target, sample_count, 494bf215546Sopenharmony_ci sample_count, tex_usage)) { 495bf215546Sopenharmony_ci fmt = formats[i]; 496bf215546Sopenharmony_ci break; 497bf215546Sopenharmony_ci } 498bf215546Sopenharmony_ci } 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_ci return fmt; 501bf215546Sopenharmony_ci} 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci/**********************************************************************/ 506bf215546Sopenharmony_ci/***** Linked list of XMesaBuffers *****/ 507bf215546Sopenharmony_ci/**********************************************************************/ 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_cistatic XMesaBuffer XMesaBufferList = NULL; 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_ci/** 513bf215546Sopenharmony_ci * Allocate a new XMesaBuffer object which corresponds to the given drawable. 514bf215546Sopenharmony_ci * Note that XMesaBuffer is derived from struct gl_framebuffer. 515bf215546Sopenharmony_ci * The new XMesaBuffer will not have any size (Width=Height=0). 516bf215546Sopenharmony_ci * 517bf215546Sopenharmony_ci * \param d the corresponding X drawable (window or pixmap) 518bf215546Sopenharmony_ci * \param type either WINDOW, PIXMAP or PBUFFER, describing d 519bf215546Sopenharmony_ci * \param vis the buffer's visual 520bf215546Sopenharmony_ci * \param cmap the window's colormap, if known. 521bf215546Sopenharmony_ci * \return new XMesaBuffer or NULL if any problem 522bf215546Sopenharmony_ci */ 523bf215546Sopenharmony_cistatic XMesaBuffer 524bf215546Sopenharmony_cicreate_xmesa_buffer(Drawable d, BufferType type, 525bf215546Sopenharmony_ci XMesaVisual vis, Colormap cmap) 526bf215546Sopenharmony_ci{ 527bf215546Sopenharmony_ci XMesaDisplay xmdpy = xmesa_init_display(vis->display); 528bf215546Sopenharmony_ci XMesaBuffer b; 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci assert(type == WINDOW || type == PIXMAP || type == PBUFFER); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci if (!xmdpy) 533bf215546Sopenharmony_ci return NULL; 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); 536bf215546Sopenharmony_ci if (!b) 537bf215546Sopenharmony_ci return NULL; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci b->ws.drawable = d; 540bf215546Sopenharmony_ci b->ws.visual = vis->visinfo->visual; 541bf215546Sopenharmony_ci b->ws.depth = vis->visinfo->depth; 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci b->xm_visual = vis; 544bf215546Sopenharmony_ci b->type = type; 545bf215546Sopenharmony_ci b->cmap = cmap; 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci get_drawable_size(vis->display, d, &b->width, &b->height); 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci /* 550bf215546Sopenharmony_ci * Create framebuffer, but we'll plug in our own renderbuffers below. 551bf215546Sopenharmony_ci */ 552bf215546Sopenharmony_ci b->stfb = xmesa_create_st_framebuffer(xmdpy, b); 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_ci /* GLX_EXT_texture_from_pixmap */ 555bf215546Sopenharmony_ci b->TextureTarget = 0; 556bf215546Sopenharmony_ci b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; 557bf215546Sopenharmony_ci b->TextureMipmap = 0; 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci /* insert buffer into linked list */ 560bf215546Sopenharmony_ci b->Next = XMesaBufferList; 561bf215546Sopenharmony_ci XMesaBufferList = b; 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci return b; 564bf215546Sopenharmony_ci} 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_ci/** 568bf215546Sopenharmony_ci * Find an XMesaBuffer by matching X display and colormap but NOT matching 569bf215546Sopenharmony_ci * the notThis buffer. 570bf215546Sopenharmony_ci */ 571bf215546Sopenharmony_ciXMesaBuffer 572bf215546Sopenharmony_cixmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis) 573bf215546Sopenharmony_ci{ 574bf215546Sopenharmony_ci XMesaBuffer b; 575bf215546Sopenharmony_ci for (b = XMesaBufferList; b; b = b->Next) { 576bf215546Sopenharmony_ci if (b->xm_visual->display == dpy && 577bf215546Sopenharmony_ci b->cmap == cmap && 578bf215546Sopenharmony_ci b != notThis) { 579bf215546Sopenharmony_ci return b; 580bf215546Sopenharmony_ci } 581bf215546Sopenharmony_ci } 582bf215546Sopenharmony_ci return NULL; 583bf215546Sopenharmony_ci} 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci 586bf215546Sopenharmony_ci/** 587bf215546Sopenharmony_ci * Remove buffer from linked list, delete if no longer referenced. 588bf215546Sopenharmony_ci */ 589bf215546Sopenharmony_cistatic void 590bf215546Sopenharmony_cixmesa_free_buffer(XMesaBuffer buffer) 591bf215546Sopenharmony_ci{ 592bf215546Sopenharmony_ci XMesaBuffer prev = NULL, b; 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci for (b = XMesaBufferList; b; b = b->Next) { 595bf215546Sopenharmony_ci if (b == buffer) { 596bf215546Sopenharmony_ci /* unlink buffer from list */ 597bf215546Sopenharmony_ci if (prev) 598bf215546Sopenharmony_ci prev->Next = buffer->Next; 599bf215546Sopenharmony_ci else 600bf215546Sopenharmony_ci XMesaBufferList = buffer->Next; 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci /* Since the X window for the XMesaBuffer is going away, we don't 603bf215546Sopenharmony_ci * want to dereference this pointer in the future. 604bf215546Sopenharmony_ci */ 605bf215546Sopenharmony_ci b->ws.drawable = 0; 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_ci /* Notify the st manager that the associated framebuffer interface 608bf215546Sopenharmony_ci * object is no longer valid. 609bf215546Sopenharmony_ci */ 610bf215546Sopenharmony_ci stapi->destroy_drawable(stapi, buffer->stfb); 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci /* XXX we should move the buffer to a delete-pending list and destroy 613bf215546Sopenharmony_ci * the buffer until it is no longer current. 614bf215546Sopenharmony_ci */ 615bf215546Sopenharmony_ci xmesa_destroy_st_framebuffer(buffer->stfb); 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ci free(buffer); 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_ci return; 620bf215546Sopenharmony_ci } 621bf215546Sopenharmony_ci /* continue search */ 622bf215546Sopenharmony_ci prev = b; 623bf215546Sopenharmony_ci } 624bf215546Sopenharmony_ci /* buffer not found in XMesaBufferList */ 625bf215546Sopenharmony_ci _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); 626bf215546Sopenharmony_ci} 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci/**********************************************************************/ 631bf215546Sopenharmony_ci/***** Misc Private Functions *****/ 632bf215546Sopenharmony_ci/**********************************************************************/ 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_ci/** 636bf215546Sopenharmony_ci * When a context is bound for the first time, we can finally finish 637bf215546Sopenharmony_ci * initializing the context's visual and buffer information. 638bf215546Sopenharmony_ci * \param v the XMesaVisual to initialize 639bf215546Sopenharmony_ci * \param b the XMesaBuffer to initialize (may be NULL) 640bf215546Sopenharmony_ci * \param window the window/pixmap we're rendering into 641bf215546Sopenharmony_ci * \param cmap the colormap associated with the window/pixmap 642bf215546Sopenharmony_ci * \return GL_TRUE=success, GL_FALSE=failure 643bf215546Sopenharmony_ci */ 644bf215546Sopenharmony_cistatic GLboolean 645bf215546Sopenharmony_ciinitialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, 646bf215546Sopenharmony_ci Drawable window, Colormap cmap) 647bf215546Sopenharmony_ci{ 648bf215546Sopenharmony_ci assert(!b || b->xm_visual == v); 649bf215546Sopenharmony_ci 650bf215546Sopenharmony_ci /* Save true bits/pixel */ 651bf215546Sopenharmony_ci v->BitsPerPixel = bits_per_pixel(v); 652bf215546Sopenharmony_ci assert(v->BitsPerPixel > 0); 653bf215546Sopenharmony_ci 654bf215546Sopenharmony_ci /* RGB WINDOW: 655bf215546Sopenharmony_ci * We support RGB rendering into almost any kind of visual. 656bf215546Sopenharmony_ci */ 657bf215546Sopenharmony_ci const int xclass = v->visualType; 658bf215546Sopenharmony_ci if (xclass != GLX_TRUE_COLOR && xclass != GLX_DIRECT_COLOR) { 659bf215546Sopenharmony_ci _mesa_warning(NULL, 660bf215546Sopenharmony_ci "XMesa: RGB mode rendering not supported in given visual.\n"); 661bf215546Sopenharmony_ci return GL_FALSE; 662bf215546Sopenharmony_ci } 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci if (v->BitsPerPixel == 32) { 665bf215546Sopenharmony_ci /* We use XImages for all front/back buffers. If an X Window or 666bf215546Sopenharmony_ci * X Pixmap is 32bpp, there's no guarantee that the alpha channel 667bf215546Sopenharmony_ci * will be preserved. For XImages we're in luck. 668bf215546Sopenharmony_ci */ 669bf215546Sopenharmony_ci v->mesa_visual.alphaBits = 8; 670bf215546Sopenharmony_ci } 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci /* 673bf215546Sopenharmony_ci * If MESA_INFO env var is set print out some debugging info 674bf215546Sopenharmony_ci * which can help Brian figure out what's going on when a user 675bf215546Sopenharmony_ci * reports bugs. 676bf215546Sopenharmony_ci */ 677bf215546Sopenharmony_ci if (getenv("MESA_INFO")) { 678bf215546Sopenharmony_ci printf("X/Mesa visual = %p\n", (void *) v); 679bf215546Sopenharmony_ci printf("X/Mesa depth = %d\n", v->visinfo->depth); 680bf215546Sopenharmony_ci printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); 681bf215546Sopenharmony_ci } 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci return GL_TRUE; 684bf215546Sopenharmony_ci} 685bf215546Sopenharmony_ci 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci 688bf215546Sopenharmony_ci#define NUM_VISUAL_TYPES 6 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ci/** 691bf215546Sopenharmony_ci * Convert an X visual type to a GLX visual type. 692bf215546Sopenharmony_ci * 693bf215546Sopenharmony_ci * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) 694bf215546Sopenharmony_ci * to be converted. 695bf215546Sopenharmony_ci * \return If \c visualType is a valid X visual type, a GLX visual type will 696bf215546Sopenharmony_ci * be returned. Otherwise \c GLX_NONE will be returned. 697bf215546Sopenharmony_ci * 698bf215546Sopenharmony_ci * \note 699bf215546Sopenharmony_ci * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the 700bf215546Sopenharmony_ci * DRI CVS tree. 701bf215546Sopenharmony_ci */ 702bf215546Sopenharmony_cistatic GLint 703bf215546Sopenharmony_cixmesa_convert_from_x_visual_type( int visualType ) 704bf215546Sopenharmony_ci{ 705bf215546Sopenharmony_ci static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { 706bf215546Sopenharmony_ci GLX_STATIC_GRAY, GLX_GRAY_SCALE, 707bf215546Sopenharmony_ci GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, 708bf215546Sopenharmony_ci GLX_TRUE_COLOR, GLX_DIRECT_COLOR 709bf215546Sopenharmony_ci }; 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci return ( (unsigned) visualType < NUM_VISUAL_TYPES ) 712bf215546Sopenharmony_ci ? glx_visual_types[ visualType ] : GLX_NONE; 713bf215546Sopenharmony_ci} 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci/**********************************************************************/ 717bf215546Sopenharmony_ci/***** Public Functions *****/ 718bf215546Sopenharmony_ci/**********************************************************************/ 719bf215546Sopenharmony_ci 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci/* 722bf215546Sopenharmony_ci * Create a new X/Mesa visual. 723bf215546Sopenharmony_ci * Input: display - X11 display 724bf215546Sopenharmony_ci * visinfo - an XVisualInfo pointer 725bf215546Sopenharmony_ci * rgb_flag - GL_TRUE = RGB mode, 726bf215546Sopenharmony_ci * GL_FALSE = color index mode 727bf215546Sopenharmony_ci * alpha_flag - alpha buffer requested? 728bf215546Sopenharmony_ci * db_flag - GL_TRUE = double-buffered, 729bf215546Sopenharmony_ci * GL_FALSE = single buffered 730bf215546Sopenharmony_ci * stereo_flag - stereo visual? 731bf215546Sopenharmony_ci * ximage_flag - GL_TRUE = use an XImage for back buffer, 732bf215546Sopenharmony_ci * GL_FALSE = use an off-screen pixmap for back buffer 733bf215546Sopenharmony_ci * depth_size - requested bits/depth values, or zero 734bf215546Sopenharmony_ci * stencil_size - requested bits/stencil values, or zero 735bf215546Sopenharmony_ci * accum_red_size - requested bits/red accum values, or zero 736bf215546Sopenharmony_ci * accum_green_size - requested bits/green accum values, or zero 737bf215546Sopenharmony_ci * accum_blue_size - requested bits/blue accum values, or zero 738bf215546Sopenharmony_ci * accum_alpha_size - requested bits/alpha accum values, or zero 739bf215546Sopenharmony_ci * num_samples - number of samples/pixel if multisampling, or zero 740bf215546Sopenharmony_ci * level - visual level, usually 0 741bf215546Sopenharmony_ci * visualCaveat - ala the GLX extension, usually GLX_NONE 742bf215546Sopenharmony_ci * Return; a new XMesaVisual or 0 if error. 743bf215546Sopenharmony_ci */ 744bf215546Sopenharmony_ciPUBLIC 745bf215546Sopenharmony_ciXMesaVisual XMesaCreateVisual( Display *display, 746bf215546Sopenharmony_ci XVisualInfo * visinfo, 747bf215546Sopenharmony_ci GLboolean rgb_flag, 748bf215546Sopenharmony_ci GLboolean alpha_flag, 749bf215546Sopenharmony_ci GLboolean db_flag, 750bf215546Sopenharmony_ci GLboolean stereo_flag, 751bf215546Sopenharmony_ci GLboolean ximage_flag, 752bf215546Sopenharmony_ci GLint depth_size, 753bf215546Sopenharmony_ci GLint stencil_size, 754bf215546Sopenharmony_ci GLint accum_red_size, 755bf215546Sopenharmony_ci GLint accum_green_size, 756bf215546Sopenharmony_ci GLint accum_blue_size, 757bf215546Sopenharmony_ci GLint accum_alpha_size, 758bf215546Sopenharmony_ci GLint num_samples, 759bf215546Sopenharmony_ci GLint level, 760bf215546Sopenharmony_ci GLint visualCaveat ) 761bf215546Sopenharmony_ci{ 762bf215546Sopenharmony_ci XMesaDisplay xmdpy = xmesa_init_display(display); 763bf215546Sopenharmony_ci XMesaVisual v; 764bf215546Sopenharmony_ci GLint red_bits, green_bits, blue_bits, alpha_bits; 765bf215546Sopenharmony_ci 766bf215546Sopenharmony_ci if (!xmdpy) 767bf215546Sopenharmony_ci return NULL; 768bf215546Sopenharmony_ci 769bf215546Sopenharmony_ci if (!rgb_flag) 770bf215546Sopenharmony_ci return NULL; 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci /* For debugging only */ 773bf215546Sopenharmony_ci if (getenv("MESA_XSYNC")) { 774bf215546Sopenharmony_ci /* This makes debugging X easier. 775bf215546Sopenharmony_ci * In your debugger, set a breakpoint on _XError to stop when an 776bf215546Sopenharmony_ci * X protocol error is generated. 777bf215546Sopenharmony_ci */ 778bf215546Sopenharmony_ci XSynchronize( display, 1 ); 779bf215546Sopenharmony_ci } 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); 782bf215546Sopenharmony_ci if (!v) { 783bf215546Sopenharmony_ci return NULL; 784bf215546Sopenharmony_ci } 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ci v->display = display; 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_ci /* Save a copy of the XVisualInfo struct because the user may Xfree() 789bf215546Sopenharmony_ci * the struct but we may need some of the information contained in it 790bf215546Sopenharmony_ci * at a later time. 791bf215546Sopenharmony_ci */ 792bf215546Sopenharmony_ci v->visinfo = malloc(sizeof(*visinfo)); 793bf215546Sopenharmony_ci if (!v->visinfo) { 794bf215546Sopenharmony_ci free(v); 795bf215546Sopenharmony_ci return NULL; 796bf215546Sopenharmony_ci } 797bf215546Sopenharmony_ci memcpy(v->visinfo, visinfo, sizeof(*visinfo)); 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci v->ximage_flag = ximage_flag; 800bf215546Sopenharmony_ci 801bf215546Sopenharmony_ci v->mesa_visual.redMask = visinfo->red_mask; 802bf215546Sopenharmony_ci v->mesa_visual.greenMask = visinfo->green_mask; 803bf215546Sopenharmony_ci v->mesa_visual.blueMask = visinfo->blue_mask; 804bf215546Sopenharmony_ci v->visualID = visinfo->visualid; 805bf215546Sopenharmony_ci v->screen = visinfo->screen; 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci#if !(defined(__cplusplus) || defined(c_plusplus)) 808bf215546Sopenharmony_ci v->visualType = xmesa_convert_from_x_visual_type(visinfo->class); 809bf215546Sopenharmony_ci#else 810bf215546Sopenharmony_ci v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); 811bf215546Sopenharmony_ci#endif 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci if (alpha_flag) 814bf215546Sopenharmony_ci v->mesa_visual.alphaBits = 8; 815bf215546Sopenharmony_ci 816bf215546Sopenharmony_ci (void) initialize_visual_and_buffer( v, NULL, 0, 0 ); 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_ci { 819bf215546Sopenharmony_ci const int xclass = v->visualType; 820bf215546Sopenharmony_ci if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { 821bf215546Sopenharmony_ci red_bits = util_bitcount(GET_REDMASK(v)); 822bf215546Sopenharmony_ci green_bits = util_bitcount(GET_GREENMASK(v)); 823bf215546Sopenharmony_ci blue_bits = util_bitcount(GET_BLUEMASK(v)); 824bf215546Sopenharmony_ci } 825bf215546Sopenharmony_ci else { 826bf215546Sopenharmony_ci /* this is an approximation */ 827bf215546Sopenharmony_ci int depth; 828bf215546Sopenharmony_ci depth = v->visinfo->depth; 829bf215546Sopenharmony_ci red_bits = depth / 3; 830bf215546Sopenharmony_ci depth -= red_bits; 831bf215546Sopenharmony_ci green_bits = depth / 2; 832bf215546Sopenharmony_ci depth -= green_bits; 833bf215546Sopenharmony_ci blue_bits = depth; 834bf215546Sopenharmony_ci alpha_bits = 0; 835bf215546Sopenharmony_ci assert( red_bits + green_bits + blue_bits == v->visinfo->depth ); 836bf215546Sopenharmony_ci } 837bf215546Sopenharmony_ci alpha_bits = v->mesa_visual.alphaBits; 838bf215546Sopenharmony_ci } 839bf215546Sopenharmony_ci 840bf215546Sopenharmony_ci /* initialize visual */ 841bf215546Sopenharmony_ci { 842bf215546Sopenharmony_ci struct gl_config *vis = &v->mesa_visual; 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_ci vis->doubleBufferMode = db_flag; 845bf215546Sopenharmony_ci vis->stereoMode = stereo_flag; 846bf215546Sopenharmony_ci 847bf215546Sopenharmony_ci vis->redBits = red_bits; 848bf215546Sopenharmony_ci vis->greenBits = green_bits; 849bf215546Sopenharmony_ci vis->blueBits = blue_bits; 850bf215546Sopenharmony_ci vis->alphaBits = alpha_bits; 851bf215546Sopenharmony_ci vis->rgbBits = red_bits + green_bits + blue_bits; 852bf215546Sopenharmony_ci 853bf215546Sopenharmony_ci vis->depthBits = depth_size; 854bf215546Sopenharmony_ci vis->stencilBits = stencil_size; 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_ci vis->accumRedBits = accum_red_size; 857bf215546Sopenharmony_ci vis->accumGreenBits = accum_green_size; 858bf215546Sopenharmony_ci vis->accumBlueBits = accum_blue_size; 859bf215546Sopenharmony_ci vis->accumAlphaBits = accum_alpha_size; 860bf215546Sopenharmony_ci 861bf215546Sopenharmony_ci vis->samples = num_samples; 862bf215546Sopenharmony_ci } 863bf215546Sopenharmony_ci 864bf215546Sopenharmony_ci v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; 865bf215546Sopenharmony_ci if (db_flag) 866bf215546Sopenharmony_ci v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 867bf215546Sopenharmony_ci if (stereo_flag) { 868bf215546Sopenharmony_ci v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; 869bf215546Sopenharmony_ci if (db_flag) 870bf215546Sopenharmony_ci v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; 871bf215546Sopenharmony_ci } 872bf215546Sopenharmony_ci 873bf215546Sopenharmony_ci v->stvis.color_format = choose_pixel_format(v); 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_ci /* Check format support at requested num_samples (for multisample) */ 876bf215546Sopenharmony_ci if (!xmdpy->screen->is_format_supported(xmdpy->screen, 877bf215546Sopenharmony_ci v->stvis.color_format, 878bf215546Sopenharmony_ci PIPE_TEXTURE_2D, num_samples, 879bf215546Sopenharmony_ci num_samples, 880bf215546Sopenharmony_ci PIPE_BIND_RENDER_TARGET)) 881bf215546Sopenharmony_ci v->stvis.color_format = PIPE_FORMAT_NONE; 882bf215546Sopenharmony_ci 883bf215546Sopenharmony_ci if (v->stvis.color_format == PIPE_FORMAT_NONE) { 884bf215546Sopenharmony_ci free(v->visinfo); 885bf215546Sopenharmony_ci free(v); 886bf215546Sopenharmony_ci return NULL; 887bf215546Sopenharmony_ci } 888bf215546Sopenharmony_ci 889bf215546Sopenharmony_ci v->stvis.depth_stencil_format = 890bf215546Sopenharmony_ci choose_depth_stencil_format(xmdpy, depth_size, stencil_size, 891bf215546Sopenharmony_ci num_samples); 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_ci v->stvis.accum_format = (accum_red_size + 894bf215546Sopenharmony_ci accum_green_size + accum_blue_size + accum_alpha_size) ? 895bf215546Sopenharmony_ci PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; 896bf215546Sopenharmony_ci 897bf215546Sopenharmony_ci v->stvis.samples = num_samples; 898bf215546Sopenharmony_ci 899bf215546Sopenharmony_ci return v; 900bf215546Sopenharmony_ci} 901bf215546Sopenharmony_ci 902bf215546Sopenharmony_ci 903bf215546Sopenharmony_ciPUBLIC 904bf215546Sopenharmony_civoid XMesaDestroyVisual( XMesaVisual v ) 905bf215546Sopenharmony_ci{ 906bf215546Sopenharmony_ci free(v->visinfo); 907bf215546Sopenharmony_ci free(v); 908bf215546Sopenharmony_ci} 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci 911bf215546Sopenharmony_ci/** 912bf215546Sopenharmony_ci * Return the informative name. 913bf215546Sopenharmony_ci */ 914bf215546Sopenharmony_ciconst char * 915bf215546Sopenharmony_cixmesa_get_name(void) 916bf215546Sopenharmony_ci{ 917bf215546Sopenharmony_ci return stapi->name; 918bf215546Sopenharmony_ci} 919bf215546Sopenharmony_ci 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_ci/** 922bf215546Sopenharmony_ci * Do per-display initializations. 923bf215546Sopenharmony_ci */ 924bf215546Sopenharmony_ciint 925bf215546Sopenharmony_cixmesa_init( Display *display ) 926bf215546Sopenharmony_ci{ 927bf215546Sopenharmony_ci return xmesa_init_display(display) ? 0 : 1; 928bf215546Sopenharmony_ci} 929bf215546Sopenharmony_ci 930bf215546Sopenharmony_ci 931bf215546Sopenharmony_ci/** 932bf215546Sopenharmony_ci * Create a new XMesaContext. 933bf215546Sopenharmony_ci * \param v the XMesaVisual 934bf215546Sopenharmony_ci * \param share_list another XMesaContext with which to share display 935bf215546Sopenharmony_ci * lists or NULL if no sharing is wanted. 936bf215546Sopenharmony_ci * \return an XMesaContext or NULL if error. 937bf215546Sopenharmony_ci */ 938bf215546Sopenharmony_ciPUBLIC 939bf215546Sopenharmony_ciXMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list, 940bf215546Sopenharmony_ci GLuint major, GLuint minor, 941bf215546Sopenharmony_ci GLuint profileMask, GLuint contextFlags) 942bf215546Sopenharmony_ci{ 943bf215546Sopenharmony_ci XMesaDisplay xmdpy = xmesa_init_display(v->display); 944bf215546Sopenharmony_ci struct st_context_attribs attribs; 945bf215546Sopenharmony_ci enum st_context_error ctx_err = 0; 946bf215546Sopenharmony_ci XMesaContext c; 947bf215546Sopenharmony_ci 948bf215546Sopenharmony_ci if (!xmdpy) 949bf215546Sopenharmony_ci goto no_xmesa_context; 950bf215546Sopenharmony_ci 951bf215546Sopenharmony_ci /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */ 952bf215546Sopenharmony_ci c = (XMesaContext) CALLOC_STRUCT(xmesa_context); 953bf215546Sopenharmony_ci if (!c) 954bf215546Sopenharmony_ci goto no_xmesa_context; 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_ci c->xm_visual = v; 957bf215546Sopenharmony_ci c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ 958bf215546Sopenharmony_ci c->xm_read_buffer = NULL; 959bf215546Sopenharmony_ci 960bf215546Sopenharmony_ci memset(&attribs, 0, sizeof(attribs)); 961bf215546Sopenharmony_ci attribs.visual = v->stvis; 962bf215546Sopenharmony_ci attribs.major = major; 963bf215546Sopenharmony_ci attribs.minor = minor; 964bf215546Sopenharmony_ci if (contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) 965bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; 966bf215546Sopenharmony_ci if (contextFlags & GLX_CONTEXT_DEBUG_BIT_ARB) 967bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_DEBUG; 968bf215546Sopenharmony_ci if (contextFlags & GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB) 969bf215546Sopenharmony_ci attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS; 970bf215546Sopenharmony_ci 971bf215546Sopenharmony_ci switch (profileMask) { 972bf215546Sopenharmony_ci case GLX_CONTEXT_CORE_PROFILE_BIT_ARB: 973bf215546Sopenharmony_ci /* There are no profiles before OpenGL 3.2. The 974bf215546Sopenharmony_ci * GLX_ARB_create_context_profile spec says: 975bf215546Sopenharmony_ci * 976bf215546Sopenharmony_ci * "If the requested OpenGL version is less than 3.2, 977bf215546Sopenharmony_ci * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality 978bf215546Sopenharmony_ci * of the context is determined solely by the requested version." 979bf215546Sopenharmony_ci */ 980bf215546Sopenharmony_ci if (major > 3 || (major == 3 && minor >= 2)) { 981bf215546Sopenharmony_ci attribs.profile = ST_PROFILE_OPENGL_CORE; 982bf215546Sopenharmony_ci break; 983bf215546Sopenharmony_ci } 984bf215546Sopenharmony_ci FALLTHROUGH; 985bf215546Sopenharmony_ci case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: 986bf215546Sopenharmony_ci /* 987bf215546Sopenharmony_ci * The spec also says: 988bf215546Sopenharmony_ci * 989bf215546Sopenharmony_ci * "If version 3.1 is requested, the context returned may implement 990bf215546Sopenharmony_ci * any of the following versions: 991bf215546Sopenharmony_ci * 992bf215546Sopenharmony_ci * * Version 3.1. The GL_ARB_compatibility extension may or may not 993bf215546Sopenharmony_ci * be implemented, as determined by the implementation. 994bf215546Sopenharmony_ci * * The core profile of version 3.2 or greater." 995bf215546Sopenharmony_ci * 996bf215546Sopenharmony_ci * and because Mesa doesn't support GL_ARB_compatibility, the only chance to 997bf215546Sopenharmony_ci * honour a 3.1 context is through core profile. 998bf215546Sopenharmony_ci */ 999bf215546Sopenharmony_ci if (major == 3 && minor == 1) { 1000bf215546Sopenharmony_ci attribs.profile = ST_PROFILE_OPENGL_CORE; 1001bf215546Sopenharmony_ci } else { 1002bf215546Sopenharmony_ci attribs.profile = ST_PROFILE_DEFAULT; 1003bf215546Sopenharmony_ci } 1004bf215546Sopenharmony_ci break; 1005bf215546Sopenharmony_ci case GLX_CONTEXT_ES_PROFILE_BIT_EXT: 1006bf215546Sopenharmony_ci if (major >= 2) { 1007bf215546Sopenharmony_ci attribs.profile = ST_PROFILE_OPENGL_ES2; 1008bf215546Sopenharmony_ci } else { 1009bf215546Sopenharmony_ci attribs.profile = ST_PROFILE_OPENGL_ES1; 1010bf215546Sopenharmony_ci } 1011bf215546Sopenharmony_ci break; 1012bf215546Sopenharmony_ci default: 1013bf215546Sopenharmony_ci assert(0); 1014bf215546Sopenharmony_ci goto no_st; 1015bf215546Sopenharmony_ci } 1016bf215546Sopenharmony_ci 1017bf215546Sopenharmony_ci c->st = stapi->create_context(stapi, xmdpy->smapi, &attribs, 1018bf215546Sopenharmony_ci &ctx_err, (share_list) ? share_list->st : NULL); 1019bf215546Sopenharmony_ci if (c->st == NULL) 1020bf215546Sopenharmony_ci goto no_st; 1021bf215546Sopenharmony_ci 1022bf215546Sopenharmony_ci c->st->st_manager_private = (void *) c; 1023bf215546Sopenharmony_ci 1024bf215546Sopenharmony_ci c->hud = hud_create(c->st->cso_context, c->st, NULL); 1025bf215546Sopenharmony_ci 1026bf215546Sopenharmony_ci return c; 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_cino_st: 1029bf215546Sopenharmony_ci free(c); 1030bf215546Sopenharmony_cino_xmesa_context: 1031bf215546Sopenharmony_ci return NULL; 1032bf215546Sopenharmony_ci} 1033bf215546Sopenharmony_ci 1034bf215546Sopenharmony_ci 1035bf215546Sopenharmony_ci 1036bf215546Sopenharmony_ciPUBLIC 1037bf215546Sopenharmony_civoid XMesaDestroyContext( XMesaContext c ) 1038bf215546Sopenharmony_ci{ 1039bf215546Sopenharmony_ci if (c->hud) { 1040bf215546Sopenharmony_ci hud_destroy(c->hud, NULL); 1041bf215546Sopenharmony_ci } 1042bf215546Sopenharmony_ci 1043bf215546Sopenharmony_ci c->st->destroy(c->st); 1044bf215546Sopenharmony_ci 1045bf215546Sopenharmony_ci /* FIXME: We should destroy the screen here, but if we do so, surfaces may 1046bf215546Sopenharmony_ci * outlive it, causing segfaults 1047bf215546Sopenharmony_ci struct pipe_screen *screen = c->st->pipe->screen; 1048bf215546Sopenharmony_ci screen->destroy(screen); 1049bf215546Sopenharmony_ci */ 1050bf215546Sopenharmony_ci 1051bf215546Sopenharmony_ci free(c); 1052bf215546Sopenharmony_ci} 1053bf215546Sopenharmony_ci 1054bf215546Sopenharmony_ci 1055bf215546Sopenharmony_ci 1056bf215546Sopenharmony_ci/** 1057bf215546Sopenharmony_ci * Private function for creating an XMesaBuffer which corresponds to an 1058bf215546Sopenharmony_ci * X window or pixmap. 1059bf215546Sopenharmony_ci * \param v the window's XMesaVisual 1060bf215546Sopenharmony_ci * \param w the window we're wrapping 1061bf215546Sopenharmony_ci * \return new XMesaBuffer or NULL if error 1062bf215546Sopenharmony_ci */ 1063bf215546Sopenharmony_ciPUBLIC XMesaBuffer 1064bf215546Sopenharmony_ciXMesaCreateWindowBuffer(XMesaVisual v, Window w) 1065bf215546Sopenharmony_ci{ 1066bf215546Sopenharmony_ci XWindowAttributes attr; 1067bf215546Sopenharmony_ci XMesaBuffer b; 1068bf215546Sopenharmony_ci Colormap cmap; 1069bf215546Sopenharmony_ci int depth; 1070bf215546Sopenharmony_ci 1071bf215546Sopenharmony_ci assert(v); 1072bf215546Sopenharmony_ci assert(w); 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci /* Check that window depth matches visual depth */ 1075bf215546Sopenharmony_ci XGetWindowAttributes( v->display, w, &attr ); 1076bf215546Sopenharmony_ci depth = attr.depth; 1077bf215546Sopenharmony_ci if (v->visinfo->depth != depth) { 1078bf215546Sopenharmony_ci _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", 1079bf215546Sopenharmony_ci v->visinfo->depth, depth); 1080bf215546Sopenharmony_ci return NULL; 1081bf215546Sopenharmony_ci } 1082bf215546Sopenharmony_ci 1083bf215546Sopenharmony_ci /* Find colormap */ 1084bf215546Sopenharmony_ci if (attr.colormap) { 1085bf215546Sopenharmony_ci cmap = attr.colormap; 1086bf215546Sopenharmony_ci } 1087bf215546Sopenharmony_ci else { 1088bf215546Sopenharmony_ci _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); 1089bf215546Sopenharmony_ci /* this is weird, a window w/out a colormap!? */ 1090bf215546Sopenharmony_ci /* OK, let's just allocate a new one and hope for the best */ 1091bf215546Sopenharmony_ci cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); 1092bf215546Sopenharmony_ci } 1093bf215546Sopenharmony_ci 1094bf215546Sopenharmony_ci b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap); 1095bf215546Sopenharmony_ci if (!b) 1096bf215546Sopenharmony_ci return NULL; 1097bf215546Sopenharmony_ci 1098bf215546Sopenharmony_ci if (!initialize_visual_and_buffer( v, b, (Drawable) w, cmap )) { 1099bf215546Sopenharmony_ci xmesa_free_buffer(b); 1100bf215546Sopenharmony_ci return NULL; 1101bf215546Sopenharmony_ci } 1102bf215546Sopenharmony_ci 1103bf215546Sopenharmony_ci return b; 1104bf215546Sopenharmony_ci} 1105bf215546Sopenharmony_ci 1106bf215546Sopenharmony_ci 1107bf215546Sopenharmony_ci 1108bf215546Sopenharmony_ci/** 1109bf215546Sopenharmony_ci * Create a new XMesaBuffer from an X pixmap. 1110bf215546Sopenharmony_ci * 1111bf215546Sopenharmony_ci * \param v the XMesaVisual 1112bf215546Sopenharmony_ci * \param p the pixmap 1113bf215546Sopenharmony_ci * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or 1114bf215546Sopenharmony_ci * \c GLX_DIRECT_COLOR visual for the pixmap 1115bf215546Sopenharmony_ci * \returns new XMesaBuffer or NULL if error 1116bf215546Sopenharmony_ci */ 1117bf215546Sopenharmony_ciPUBLIC XMesaBuffer 1118bf215546Sopenharmony_ciXMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap) 1119bf215546Sopenharmony_ci{ 1120bf215546Sopenharmony_ci XMesaBuffer b; 1121bf215546Sopenharmony_ci 1122bf215546Sopenharmony_ci assert(v); 1123bf215546Sopenharmony_ci 1124bf215546Sopenharmony_ci b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); 1125bf215546Sopenharmony_ci if (!b) 1126bf215546Sopenharmony_ci return NULL; 1127bf215546Sopenharmony_ci 1128bf215546Sopenharmony_ci if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) { 1129bf215546Sopenharmony_ci xmesa_free_buffer(b); 1130bf215546Sopenharmony_ci return NULL; 1131bf215546Sopenharmony_ci } 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci return b; 1134bf215546Sopenharmony_ci} 1135bf215546Sopenharmony_ci 1136bf215546Sopenharmony_ci 1137bf215546Sopenharmony_ci/** 1138bf215546Sopenharmony_ci * For GLX_EXT_texture_from_pixmap 1139bf215546Sopenharmony_ci */ 1140bf215546Sopenharmony_ciXMesaBuffer 1141bf215546Sopenharmony_ciXMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, 1142bf215546Sopenharmony_ci Colormap cmap, 1143bf215546Sopenharmony_ci int format, int target, int mipmap) 1144bf215546Sopenharmony_ci{ 1145bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1146bf215546Sopenharmony_ci XMesaBuffer b; 1147bf215546Sopenharmony_ci 1148bf215546Sopenharmony_ci assert(v); 1149bf215546Sopenharmony_ci 1150bf215546Sopenharmony_ci b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); 1151bf215546Sopenharmony_ci if (!b) 1152bf215546Sopenharmony_ci return NULL; 1153bf215546Sopenharmony_ci 1154bf215546Sopenharmony_ci /* get pixmap size */ 1155bf215546Sopenharmony_ci xmesa_get_window_size(v->display, b, &b->width, &b->height); 1156bf215546Sopenharmony_ci 1157bf215546Sopenharmony_ci if (target == 0) { 1158bf215546Sopenharmony_ci /* examine dims */ 1159bf215546Sopenharmony_ci if (ctx->Extensions.ARB_texture_non_power_of_two) { 1160bf215546Sopenharmony_ci target = GLX_TEXTURE_2D_EXT; 1161bf215546Sopenharmony_ci } 1162bf215546Sopenharmony_ci else if ( util_bitcount(b->width) == 1 1163bf215546Sopenharmony_ci && util_bitcount(b->height) == 1) { 1164bf215546Sopenharmony_ci /* power of two size */ 1165bf215546Sopenharmony_ci if (b->height == 1) { 1166bf215546Sopenharmony_ci target = GLX_TEXTURE_1D_EXT; 1167bf215546Sopenharmony_ci } 1168bf215546Sopenharmony_ci else { 1169bf215546Sopenharmony_ci target = GLX_TEXTURE_2D_EXT; 1170bf215546Sopenharmony_ci } 1171bf215546Sopenharmony_ci } 1172bf215546Sopenharmony_ci else if (ctx->Extensions.NV_texture_rectangle) { 1173bf215546Sopenharmony_ci target = GLX_TEXTURE_RECTANGLE_EXT; 1174bf215546Sopenharmony_ci } 1175bf215546Sopenharmony_ci else { 1176bf215546Sopenharmony_ci /* non power of two textures not supported */ 1177bf215546Sopenharmony_ci XMesaDestroyBuffer(b); 1178bf215546Sopenharmony_ci return 0; 1179bf215546Sopenharmony_ci } 1180bf215546Sopenharmony_ci } 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_ci b->TextureTarget = target; 1183bf215546Sopenharmony_ci b->TextureFormat = format; 1184bf215546Sopenharmony_ci b->TextureMipmap = mipmap; 1185bf215546Sopenharmony_ci 1186bf215546Sopenharmony_ci if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) { 1187bf215546Sopenharmony_ci xmesa_free_buffer(b); 1188bf215546Sopenharmony_ci return NULL; 1189bf215546Sopenharmony_ci } 1190bf215546Sopenharmony_ci 1191bf215546Sopenharmony_ci return b; 1192bf215546Sopenharmony_ci} 1193bf215546Sopenharmony_ci 1194bf215546Sopenharmony_ci 1195bf215546Sopenharmony_ci 1196bf215546Sopenharmony_ciXMesaBuffer 1197bf215546Sopenharmony_ciXMesaCreatePBuffer(XMesaVisual v, Colormap cmap, 1198bf215546Sopenharmony_ci unsigned int width, unsigned int height) 1199bf215546Sopenharmony_ci{ 1200bf215546Sopenharmony_ci Window root; 1201bf215546Sopenharmony_ci Drawable drawable; /* X Pixmap Drawable */ 1202bf215546Sopenharmony_ci XMesaBuffer b; 1203bf215546Sopenharmony_ci 1204bf215546Sopenharmony_ci /* allocate pixmap for front buffer */ 1205bf215546Sopenharmony_ci root = RootWindow( v->display, v->visinfo->screen ); 1206bf215546Sopenharmony_ci drawable = XCreatePixmap(v->display, root, width, height, 1207bf215546Sopenharmony_ci v->visinfo->depth); 1208bf215546Sopenharmony_ci if (!drawable) 1209bf215546Sopenharmony_ci return NULL; 1210bf215546Sopenharmony_ci 1211bf215546Sopenharmony_ci b = create_xmesa_buffer(drawable, PBUFFER, v, cmap); 1212bf215546Sopenharmony_ci if (!b) 1213bf215546Sopenharmony_ci return NULL; 1214bf215546Sopenharmony_ci 1215bf215546Sopenharmony_ci if (!initialize_visual_and_buffer(v, b, drawable, cmap)) { 1216bf215546Sopenharmony_ci xmesa_free_buffer(b); 1217bf215546Sopenharmony_ci return NULL; 1218bf215546Sopenharmony_ci } 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_ci return b; 1221bf215546Sopenharmony_ci} 1222bf215546Sopenharmony_ci 1223bf215546Sopenharmony_ci 1224bf215546Sopenharmony_ci 1225bf215546Sopenharmony_ci/* 1226bf215546Sopenharmony_ci * Deallocate an XMesaBuffer structure and all related info. 1227bf215546Sopenharmony_ci */ 1228bf215546Sopenharmony_ciPUBLIC void 1229bf215546Sopenharmony_ciXMesaDestroyBuffer(XMesaBuffer b) 1230bf215546Sopenharmony_ci{ 1231bf215546Sopenharmony_ci xmesa_free_buffer(b); 1232bf215546Sopenharmony_ci} 1233bf215546Sopenharmony_ci 1234bf215546Sopenharmony_ci 1235bf215546Sopenharmony_ci/** 1236bf215546Sopenharmony_ci * Notify the binding context to validate the buffer. 1237bf215546Sopenharmony_ci */ 1238bf215546Sopenharmony_civoid 1239bf215546Sopenharmony_cixmesa_notify_invalid_buffer(XMesaBuffer b) 1240bf215546Sopenharmony_ci{ 1241bf215546Sopenharmony_ci p_atomic_inc(&b->stfb->stamp); 1242bf215546Sopenharmony_ci} 1243bf215546Sopenharmony_ci 1244bf215546Sopenharmony_ci 1245bf215546Sopenharmony_ci/** 1246bf215546Sopenharmony_ci * Query the current drawable size and notify the binding context. 1247bf215546Sopenharmony_ci */ 1248bf215546Sopenharmony_civoid 1249bf215546Sopenharmony_cixmesa_check_buffer_size(XMesaBuffer b) 1250bf215546Sopenharmony_ci{ 1251bf215546Sopenharmony_ci GLuint old_width, old_height; 1252bf215546Sopenharmony_ci 1253bf215546Sopenharmony_ci if (!b) 1254bf215546Sopenharmony_ci return; 1255bf215546Sopenharmony_ci 1256bf215546Sopenharmony_ci if (b->type == PBUFFER) 1257bf215546Sopenharmony_ci return; 1258bf215546Sopenharmony_ci 1259bf215546Sopenharmony_ci old_width = b->width; 1260bf215546Sopenharmony_ci old_height = b->height; 1261bf215546Sopenharmony_ci 1262bf215546Sopenharmony_ci xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height); 1263bf215546Sopenharmony_ci 1264bf215546Sopenharmony_ci if (b->width != old_width || b->height != old_height) 1265bf215546Sopenharmony_ci xmesa_notify_invalid_buffer(b); 1266bf215546Sopenharmony_ci} 1267bf215546Sopenharmony_ci 1268bf215546Sopenharmony_ci 1269bf215546Sopenharmony_ci/* 1270bf215546Sopenharmony_ci * Bind buffer b to context c and make c the current rendering context. 1271bf215546Sopenharmony_ci */ 1272bf215546Sopenharmony_ciPUBLIC 1273bf215546Sopenharmony_ciGLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, 1274bf215546Sopenharmony_ci XMesaBuffer readBuffer ) 1275bf215546Sopenharmony_ci{ 1276bf215546Sopenharmony_ci XMesaContext old_ctx = XMesaGetCurrentContext(); 1277bf215546Sopenharmony_ci 1278bf215546Sopenharmony_ci if (old_ctx && old_ctx != c) { 1279bf215546Sopenharmony_ci XMesaFlush(old_ctx); 1280bf215546Sopenharmony_ci old_ctx->xm_buffer = NULL; 1281bf215546Sopenharmony_ci old_ctx->xm_read_buffer = NULL; 1282bf215546Sopenharmony_ci } 1283bf215546Sopenharmony_ci 1284bf215546Sopenharmony_ci if (c) { 1285bf215546Sopenharmony_ci if (!drawBuffer != !readBuffer) { 1286bf215546Sopenharmony_ci return GL_FALSE; /* must specify zero or two buffers! */ 1287bf215546Sopenharmony_ci } 1288bf215546Sopenharmony_ci 1289bf215546Sopenharmony_ci if (c == old_ctx && 1290bf215546Sopenharmony_ci c->xm_buffer == drawBuffer && 1291bf215546Sopenharmony_ci c->xm_read_buffer == readBuffer) 1292bf215546Sopenharmony_ci return GL_TRUE; 1293bf215546Sopenharmony_ci 1294bf215546Sopenharmony_ci xmesa_check_buffer_size(drawBuffer); 1295bf215546Sopenharmony_ci if (readBuffer != drawBuffer) 1296bf215546Sopenharmony_ci xmesa_check_buffer_size(readBuffer); 1297bf215546Sopenharmony_ci 1298bf215546Sopenharmony_ci c->xm_buffer = drawBuffer; 1299bf215546Sopenharmony_ci c->xm_read_buffer = readBuffer; 1300bf215546Sopenharmony_ci 1301bf215546Sopenharmony_ci stapi->make_current(stapi, c->st, 1302bf215546Sopenharmony_ci drawBuffer ? drawBuffer->stfb : NULL, 1303bf215546Sopenharmony_ci readBuffer ? readBuffer->stfb : NULL); 1304bf215546Sopenharmony_ci 1305bf215546Sopenharmony_ci /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ 1306bf215546Sopenharmony_ci if (drawBuffer) 1307bf215546Sopenharmony_ci drawBuffer->wasCurrent = GL_TRUE; 1308bf215546Sopenharmony_ci } 1309bf215546Sopenharmony_ci else { 1310bf215546Sopenharmony_ci /* Detach */ 1311bf215546Sopenharmony_ci stapi->make_current(stapi, NULL, NULL, NULL); 1312bf215546Sopenharmony_ci 1313bf215546Sopenharmony_ci } 1314bf215546Sopenharmony_ci return GL_TRUE; 1315bf215546Sopenharmony_ci} 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_ci 1318bf215546Sopenharmony_ci/* 1319bf215546Sopenharmony_ci * Unbind the context c from its buffer. 1320bf215546Sopenharmony_ci */ 1321bf215546Sopenharmony_ciGLboolean XMesaUnbindContext( XMesaContext c ) 1322bf215546Sopenharmony_ci{ 1323bf215546Sopenharmony_ci /* A no-op for XFree86 integration purposes */ 1324bf215546Sopenharmony_ci return GL_TRUE; 1325bf215546Sopenharmony_ci} 1326bf215546Sopenharmony_ci 1327bf215546Sopenharmony_ci 1328bf215546Sopenharmony_ciXMesaContext XMesaGetCurrentContext( void ) 1329bf215546Sopenharmony_ci{ 1330bf215546Sopenharmony_ci struct st_context_iface *st = stapi->get_current(stapi); 1331bf215546Sopenharmony_ci return (XMesaContext) (st) ? st->st_manager_private : NULL; 1332bf215546Sopenharmony_ci} 1333bf215546Sopenharmony_ci 1334bf215546Sopenharmony_ci 1335bf215546Sopenharmony_ci 1336bf215546Sopenharmony_ci/** 1337bf215546Sopenharmony_ci * Swap front and back color buffers and have winsys display front buffer. 1338bf215546Sopenharmony_ci * If there's no front color buffer no swap actually occurs. 1339bf215546Sopenharmony_ci */ 1340bf215546Sopenharmony_ciPUBLIC 1341bf215546Sopenharmony_civoid XMesaSwapBuffers( XMesaBuffer b ) 1342bf215546Sopenharmony_ci{ 1343bf215546Sopenharmony_ci XMesaContext xmctx = XMesaGetCurrentContext(); 1344bf215546Sopenharmony_ci 1345bf215546Sopenharmony_ci /* Need to draw HUD before flushing */ 1346bf215546Sopenharmony_ci if (xmctx && xmctx->hud) { 1347bf215546Sopenharmony_ci struct pipe_resource *back = 1348bf215546Sopenharmony_ci xmesa_get_framebuffer_resource(b->stfb, ST_ATTACHMENT_BACK_LEFT); 1349bf215546Sopenharmony_ci hud_run(xmctx->hud, NULL, back); 1350bf215546Sopenharmony_ci } 1351bf215546Sopenharmony_ci 1352bf215546Sopenharmony_ci if (xmctx && xmctx->xm_buffer == b) { 1353bf215546Sopenharmony_ci xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); 1354bf215546Sopenharmony_ci } 1355bf215546Sopenharmony_ci 1356bf215546Sopenharmony_ci xmesa_swap_st_framebuffer(b->stfb); 1357bf215546Sopenharmony_ci} 1358bf215546Sopenharmony_ci 1359bf215546Sopenharmony_ci 1360bf215546Sopenharmony_ci 1361bf215546Sopenharmony_ci/* 1362bf215546Sopenharmony_ci * Copy sub-region of back buffer to front buffer 1363bf215546Sopenharmony_ci */ 1364bf215546Sopenharmony_civoid XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) 1365bf215546Sopenharmony_ci{ 1366bf215546Sopenharmony_ci XMesaContext xmctx = XMesaGetCurrentContext(); 1367bf215546Sopenharmony_ci 1368bf215546Sopenharmony_ci xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); 1369bf215546Sopenharmony_ci 1370bf215546Sopenharmony_ci xmesa_copy_st_framebuffer(b->stfb, 1371bf215546Sopenharmony_ci ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT, 1372bf215546Sopenharmony_ci x, b->height - y - height, width, height); 1373bf215546Sopenharmony_ci} 1374bf215546Sopenharmony_ci 1375bf215546Sopenharmony_ci 1376bf215546Sopenharmony_ci 1377bf215546Sopenharmony_civoid XMesaFlush( XMesaContext c ) 1378bf215546Sopenharmony_ci{ 1379bf215546Sopenharmony_ci if (c && c->xm_visual->display) { 1380bf215546Sopenharmony_ci XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display); 1381bf215546Sopenharmony_ci struct pipe_fence_handle *fence = NULL; 1382bf215546Sopenharmony_ci 1383bf215546Sopenharmony_ci c->st->flush(c->st, ST_FLUSH_FRONT, &fence, NULL, NULL); 1384bf215546Sopenharmony_ci if (fence) { 1385bf215546Sopenharmony_ci xmdpy->screen->fence_finish(xmdpy->screen, NULL, fence, 1386bf215546Sopenharmony_ci PIPE_TIMEOUT_INFINITE); 1387bf215546Sopenharmony_ci xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL); 1388bf215546Sopenharmony_ci } 1389bf215546Sopenharmony_ci XFlush( c->xm_visual->display ); 1390bf215546Sopenharmony_ci } 1391bf215546Sopenharmony_ci} 1392bf215546Sopenharmony_ci 1393bf215546Sopenharmony_ci 1394bf215546Sopenharmony_ci 1395bf215546Sopenharmony_ci 1396bf215546Sopenharmony_ci 1397bf215546Sopenharmony_ciXMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d ) 1398bf215546Sopenharmony_ci{ 1399bf215546Sopenharmony_ci XMesaBuffer b; 1400bf215546Sopenharmony_ci for (b = XMesaBufferList; b; b = b->Next) { 1401bf215546Sopenharmony_ci if (b->ws.drawable == d && b->xm_visual->display == dpy) { 1402bf215546Sopenharmony_ci return b; 1403bf215546Sopenharmony_ci } 1404bf215546Sopenharmony_ci } 1405bf215546Sopenharmony_ci return NULL; 1406bf215546Sopenharmony_ci} 1407bf215546Sopenharmony_ci 1408bf215546Sopenharmony_ci 1409bf215546Sopenharmony_ci/** 1410bf215546Sopenharmony_ci * Free/destroy all XMesaBuffers associated with given display. 1411bf215546Sopenharmony_ci */ 1412bf215546Sopenharmony_civoid xmesa_destroy_buffers_on_display(Display *dpy) 1413bf215546Sopenharmony_ci{ 1414bf215546Sopenharmony_ci XMesaBuffer b, next; 1415bf215546Sopenharmony_ci for (b = XMesaBufferList; b; b = next) { 1416bf215546Sopenharmony_ci next = b->Next; 1417bf215546Sopenharmony_ci if (b->xm_visual->display == dpy) { 1418bf215546Sopenharmony_ci xmesa_free_buffer(b); 1419bf215546Sopenharmony_ci /* delete head of list? */ 1420bf215546Sopenharmony_ci if (XMesaBufferList == b) { 1421bf215546Sopenharmony_ci XMesaBufferList = next; 1422bf215546Sopenharmony_ci } 1423bf215546Sopenharmony_ci } 1424bf215546Sopenharmony_ci } 1425bf215546Sopenharmony_ci} 1426bf215546Sopenharmony_ci 1427bf215546Sopenharmony_ci 1428bf215546Sopenharmony_ci/* 1429bf215546Sopenharmony_ci * Look for XMesaBuffers whose X window has been destroyed. 1430bf215546Sopenharmony_ci * Deallocate any such XMesaBuffers. 1431bf215546Sopenharmony_ci */ 1432bf215546Sopenharmony_civoid XMesaGarbageCollect( void ) 1433bf215546Sopenharmony_ci{ 1434bf215546Sopenharmony_ci XMesaBuffer b, next; 1435bf215546Sopenharmony_ci for (b=XMesaBufferList; b; b=next) { 1436bf215546Sopenharmony_ci next = b->Next; 1437bf215546Sopenharmony_ci if (b->xm_visual && 1438bf215546Sopenharmony_ci b->xm_visual->display && 1439bf215546Sopenharmony_ci b->ws.drawable && 1440bf215546Sopenharmony_ci b->type == WINDOW) { 1441bf215546Sopenharmony_ci XSync(b->xm_visual->display, False); 1442bf215546Sopenharmony_ci if (!window_exists( b->xm_visual->display, b->ws.drawable )) { 1443bf215546Sopenharmony_ci /* found a dead window, free the ancillary info */ 1444bf215546Sopenharmony_ci XMesaDestroyBuffer( b ); 1445bf215546Sopenharmony_ci } 1446bf215546Sopenharmony_ci } 1447bf215546Sopenharmony_ci } 1448bf215546Sopenharmony_ci} 1449bf215546Sopenharmony_ci 1450bf215546Sopenharmony_ci 1451bf215546Sopenharmony_cistatic enum st_attachment_type xmesa_attachment_type(int glx_attachment) 1452bf215546Sopenharmony_ci{ 1453bf215546Sopenharmony_ci switch(glx_attachment) { 1454bf215546Sopenharmony_ci case GLX_FRONT_LEFT_EXT: 1455bf215546Sopenharmony_ci return ST_ATTACHMENT_FRONT_LEFT; 1456bf215546Sopenharmony_ci case GLX_FRONT_RIGHT_EXT: 1457bf215546Sopenharmony_ci return ST_ATTACHMENT_FRONT_RIGHT; 1458bf215546Sopenharmony_ci case GLX_BACK_LEFT_EXT: 1459bf215546Sopenharmony_ci return ST_ATTACHMENT_BACK_LEFT; 1460bf215546Sopenharmony_ci case GLX_BACK_RIGHT_EXT: 1461bf215546Sopenharmony_ci return ST_ATTACHMENT_BACK_RIGHT; 1462bf215546Sopenharmony_ci default: 1463bf215546Sopenharmony_ci assert(0); 1464bf215546Sopenharmony_ci return ST_ATTACHMENT_FRONT_LEFT; 1465bf215546Sopenharmony_ci } 1466bf215546Sopenharmony_ci} 1467bf215546Sopenharmony_ci 1468bf215546Sopenharmony_ci 1469bf215546Sopenharmony_ciPUBLIC void 1470bf215546Sopenharmony_ciXMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, 1471bf215546Sopenharmony_ci const int *attrib_list) 1472bf215546Sopenharmony_ci{ 1473bf215546Sopenharmony_ci struct st_context_iface *st = stapi->get_current(stapi); 1474bf215546Sopenharmony_ci struct st_framebuffer_iface* stfbi = drawable->stfb; 1475bf215546Sopenharmony_ci struct pipe_resource *res; 1476bf215546Sopenharmony_ci int x, y, w, h; 1477bf215546Sopenharmony_ci enum st_attachment_type st_attachment = xmesa_attachment_type(buffer); 1478bf215546Sopenharmony_ci 1479bf215546Sopenharmony_ci x = 0; 1480bf215546Sopenharmony_ci y = 0; 1481bf215546Sopenharmony_ci w = drawable->width; 1482bf215546Sopenharmony_ci h = drawable->height; 1483bf215546Sopenharmony_ci 1484bf215546Sopenharmony_ci /* We need to validate our attachments before using them, 1485bf215546Sopenharmony_ci * in case the texture doesn't exist yet. */ 1486bf215546Sopenharmony_ci xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment); 1487bf215546Sopenharmony_ci res = xmesa_get_attachment(stfbi, st_attachment); 1488bf215546Sopenharmony_ci 1489bf215546Sopenharmony_ci if (res) { 1490bf215546Sopenharmony_ci struct pipe_context* pipe = xmesa_get_context(stfbi); 1491bf215546Sopenharmony_ci enum pipe_format internal_format = res->format; 1492bf215546Sopenharmony_ci struct pipe_transfer *tex_xfer; 1493bf215546Sopenharmony_ci char *map; 1494bf215546Sopenharmony_ci int line, byte_width; 1495bf215546Sopenharmony_ci XImage *img; 1496bf215546Sopenharmony_ci 1497bf215546Sopenharmony_ci internal_format = choose_pixel_format(drawable->xm_visual); 1498bf215546Sopenharmony_ci 1499bf215546Sopenharmony_ci map = pipe_texture_map(pipe, res, 1500bf215546Sopenharmony_ci 0, 0, /* level, layer */ 1501bf215546Sopenharmony_ci PIPE_MAP_WRITE, 1502bf215546Sopenharmony_ci x, y, 1503bf215546Sopenharmony_ci w, h, &tex_xfer); 1504bf215546Sopenharmony_ci if (!map) 1505bf215546Sopenharmony_ci return; 1506bf215546Sopenharmony_ci 1507bf215546Sopenharmony_ci /* Grab the XImage that we want to turn into a texture. */ 1508bf215546Sopenharmony_ci img = XGetImage(dpy, 1509bf215546Sopenharmony_ci drawable->ws.drawable, 1510bf215546Sopenharmony_ci x, y, 1511bf215546Sopenharmony_ci w, h, 1512bf215546Sopenharmony_ci AllPlanes, 1513bf215546Sopenharmony_ci ZPixmap); 1514bf215546Sopenharmony_ci 1515bf215546Sopenharmony_ci if (!img) { 1516bf215546Sopenharmony_ci pipe_texture_unmap(pipe, tex_xfer); 1517bf215546Sopenharmony_ci return; 1518bf215546Sopenharmony_ci } 1519bf215546Sopenharmony_ci 1520bf215546Sopenharmony_ci /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. */ 1521bf215546Sopenharmony_ci byte_width = w * ((img->bits_per_pixel + 7) / 8); 1522bf215546Sopenharmony_ci 1523bf215546Sopenharmony_ci for (line = 0; line < h; line++) 1524bf215546Sopenharmony_ci memcpy(&map[line * tex_xfer->stride], 1525bf215546Sopenharmony_ci &img->data[line * img->bytes_per_line], 1526bf215546Sopenharmony_ci byte_width); 1527bf215546Sopenharmony_ci 1528bf215546Sopenharmony_ci pipe_texture_unmap(pipe, tex_xfer); 1529bf215546Sopenharmony_ci 1530bf215546Sopenharmony_ci st->teximage(st, 1531bf215546Sopenharmony_ci ST_TEXTURE_2D, 1532bf215546Sopenharmony_ci 0, /* level */ 1533bf215546Sopenharmony_ci internal_format, 1534bf215546Sopenharmony_ci res, 1535bf215546Sopenharmony_ci FALSE /* no mipmap */); 1536bf215546Sopenharmony_ci 1537bf215546Sopenharmony_ci } 1538bf215546Sopenharmony_ci} 1539bf215546Sopenharmony_ci 1540bf215546Sopenharmony_ci 1541bf215546Sopenharmony_ci 1542bf215546Sopenharmony_ciPUBLIC void 1543bf215546Sopenharmony_ciXMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) 1544bf215546Sopenharmony_ci{ 1545bf215546Sopenharmony_ci} 1546bf215546Sopenharmony_ci 1547bf215546Sopenharmony_ci 1548bf215546Sopenharmony_civoid 1549bf215546Sopenharmony_ciXMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask) 1550bf215546Sopenharmony_ci{ 1551bf215546Sopenharmony_ci if (dst->st->copy) 1552bf215546Sopenharmony_ci dst->st->copy(dst->st, src->st, mask); 1553bf215546Sopenharmony_ci} 1554