Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the "Software"), |
||
8 | * to deal in the Software without restriction, including without limitation |
||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
10 | * and/or sell copies of the Software, and to permit persons to whom the |
||
11 | * Software is furnished to do so, subject to the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included |
||
14 | * in all copies or substantial portions of the Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
22 | * OTHER DEALINGS IN THE SOFTWARE. |
||
23 | */ |
||
24 | |||
25 | /** |
||
26 | * \file xm_api.c |
||
27 | * |
||
28 | * All the XMesa* API functions. |
||
29 | * |
||
30 | * |
||
31 | * NOTES: |
||
32 | * |
||
33 | * The window coordinate system origin (0,0) is in the lower-left corner |
||
34 | * of the window. X11's window coordinate origin is in the upper-left |
||
35 | * corner of the window. Therefore, most drawing functions in this |
||
36 | * file have to flip Y coordinates. |
||
37 | * |
||
38 | * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile |
||
39 | * in support for the MIT Shared Memory extension. If enabled, when you |
||
40 | * use an Ximage for the back buffer in double buffered mode, the "swap" |
||
41 | * operation will be faster. You must also link with -lXext. |
||
42 | * |
||
43 | * Byte swapping: If the Mesa host and the X display use a different |
||
44 | * byte order then there's some trickiness to be aware of when using |
||
45 | * XImages. The byte ordering used for the XImage is that of the X |
||
46 | * display, not the Mesa host. |
||
47 | * The color-to-pixel encoding for True/DirectColor must be done |
||
48 | * according to the display's visual red_mask, green_mask, and blue_mask. |
||
49 | * If XPutPixel is used to put a pixel into an XImage then XPutPixel will |
||
50 | * do byte swapping if needed. If one wants to directly "poke" the pixel |
||
51 | * into the XImage's buffer then the pixel must be byte swapped first. In |
||
52 | * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format |
||
53 | * and use XPutPixel everywhere except in the implementation of |
||
54 | * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so |
||
55 | * instead of using XPutPixel we "poke" our values after byte-swapping |
||
56 | * the clear pixel value if needed. |
||
57 | * |
||
58 | */ |
||
59 | |||
60 | #ifdef __CYGWIN__ |
||
61 | #undef WIN32 |
||
62 | #undef __WIN32__ |
||
63 | #endif |
||
64 | |||
65 | #include "glxheader.h" |
||
66 | #include "xmesaP.h" |
||
67 | #include "main/api_exec.h" |
||
68 | #include "main/context.h" |
||
69 | #include "main/extensions.h" |
||
70 | #include "main/framebuffer.h" |
||
71 | #include "main/imports.h" |
||
72 | #include "main/macros.h" |
||
73 | #include "main/renderbuffer.h" |
||
74 | #include "main/teximage.h" |
||
75 | #include "main/version.h" |
||
76 | #include "main/vtxfmt.h" |
||
77 | #include "glapi/glthread.h" |
||
78 | #include "swrast/swrast.h" |
||
79 | #include "swrast/s_renderbuffer.h" |
||
80 | #include "swrast_setup/swrast_setup.h" |
||
81 | #include "vbo/vbo.h" |
||
82 | #include "tnl/tnl.h" |
||
83 | #include "tnl/t_context.h" |
||
84 | #include "tnl/t_pipeline.h" |
||
85 | #include "drivers/common/driverfuncs.h" |
||
86 | #include "drivers/common/meta.h" |
||
87 | |||
88 | /** |
||
89 | * Global X driver lock |
||
90 | */ |
||
91 | _glthread_Mutex _xmesa_lock; |
||
92 | |||
93 | |||
94 | |||
95 | /**********************************************************************/ |
||
96 | /***** X Utility Functions *****/ |
||
97 | /**********************************************************************/ |
||
98 | |||
99 | |||
100 | /** |
||
101 | * Return the host's byte order as LSBFirst or MSBFirst ala X. |
||
102 | */ |
||
103 | static int host_byte_order( void ) |
||
104 | { |
||
105 | int i = 1; |
||
106 | char *cptr = (char *) &i; |
||
107 | return (*cptr==1) ? LSBFirst : MSBFirst; |
||
108 | } |
||
109 | |||
110 | |||
111 | /** |
||
112 | * Check if the X Shared Memory extension is available. |
||
113 | * Return: 0 = not available |
||
114 | * 1 = shared XImage support available |
||
115 | * 2 = shared Pixmap support available also |
||
116 | */ |
||
117 | static int check_for_xshm( XMesaDisplay *display ) |
||
118 | { |
||
119 | #if defined(USE_XSHM) |
||
120 | int ignore; |
||
121 | |||
122 | if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { |
||
123 | /* Note: we're no longer calling XShmQueryVersion() here. It seems |
||
124 | * to be flakey (triggers a spurious X protocol error when we close |
||
125 | * one display connection and start using a new one. XShm has been |
||
126 | * around a long time and hasn't changed so if MIT_SHM is supported |
||
127 | * we assume we're good to go. |
||
128 | */ |
||
129 | return 2; |
||
130 | } |
||
131 | else { |
||
132 | return 0; |
||
133 | } |
||
134 | #else |
||
135 | /* No XSHM support */ |
||
136 | return 0; |
||
137 | #endif |
||
138 | } |
||
139 | |||
140 | |||
141 | /** |
||
142 | * Apply gamma correction to an intensity value in [0..max]. Return the |
||
143 | * new intensity value. |
||
144 | */ |
||
145 | static GLint |
||
146 | gamma_adjust( GLfloat gamma, GLint value, GLint max ) |
||
147 | { |
||
148 | if (gamma == 1.0) { |
||
149 | return value; |
||
150 | } |
||
151 | else { |
||
152 | double x = (double) value / (double) max; |
||
153 | return IROUND_POS((GLfloat) max * pow(x, 1.0F/gamma)); |
||
154 | } |
||
155 | } |
||
156 | |||
157 | |||
158 | |||
159 | /** |
||
160 | * Return the true number of bits per pixel for XImages. |
||
161 | * For example, if we request a 24-bit deep visual we may actually need/get |
||
162 | * 32bpp XImages. This function returns the appropriate bpp. |
||
163 | * Input: dpy - the X display |
||
164 | * visinfo - desribes the visual to be used for XImages |
||
165 | * Return: true number of bits per pixel for XImages |
||
166 | */ |
||
167 | static int |
||
168 | bits_per_pixel( XMesaVisual xmv ) |
||
169 | { |
||
170 | XMesaDisplay *dpy = xmv->display; |
||
171 | XMesaVisualInfo visinfo = xmv->visinfo; |
||
172 | XMesaImage *img; |
||
173 | int bitsPerPixel; |
||
174 | /* Create a temporary XImage */ |
||
175 | img = XCreateImage( dpy, visinfo->visual, visinfo->depth, |
||
176 | ZPixmap, 0, /*format, offset*/ |
||
177 | malloc(8), /*data*/ |
||
178 | 1, 1, /*width, height*/ |
||
179 | 32, /*bitmap_pad*/ |
||
180 | |||
181 | ); |
||
182 | assert(img); |
||
183 | /* grab the bits/pixel value */ |
||
184 | bitsPerPixel = img->bits_per_pixel; |
||
185 | /* free the XImage */ |
||
186 | free( img->data ); |
||
187 | img->data = NULL; |
||
188 | XMesaDestroyImage( img ); |
||
189 | return bitsPerPixel; |
||
190 | } |
||
191 | |||
192 | |||
193 | |||
194 | /* |
||
195 | * Determine if a given X window ID is valid (window exists). |
||
196 | * Do this by calling XGetWindowAttributes() for the window and |
||
197 | * checking if we catch an X error. |
||
198 | * Input: dpy - the display |
||
199 | * win - the window to check for existance |
||
200 | * Return: GL_TRUE - window exists |
||
201 | * GL_FALSE - window doesn't exist |
||
202 | */ |
||
203 | static GLboolean WindowExistsFlag; |
||
204 | |||
205 | static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr ) |
||
206 | { |
||
207 | (void) dpy; |
||
208 | if (xerr->error_code == BadWindow) { |
||
209 | WindowExistsFlag = GL_FALSE; |
||
210 | } |
||
211 | return 0; |
||
212 | } |
||
213 | |||
214 | static GLboolean window_exists( XMesaDisplay *dpy, Window win ) |
||
215 | { |
||
216 | XWindowAttributes wa; |
||
217 | int (*old_handler)( XMesaDisplay*, XErrorEvent* ); |
||
218 | WindowExistsFlag = GL_TRUE; |
||
219 | old_handler = XSetErrorHandler(window_exists_err_handler); |
||
220 | XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ |
||
221 | XSetErrorHandler(old_handler); |
||
222 | return WindowExistsFlag; |
||
223 | } |
||
224 | |||
225 | static Status |
||
226 | get_drawable_size( XMesaDisplay *dpy, Drawable d, GLuint *width, GLuint *height ) |
||
227 | { |
||
228 | Window root; |
||
229 | Status stat; |
||
230 | int xpos, ypos; |
||
231 | unsigned int w, h, bw, depth; |
||
232 | stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); |
||
233 | *width = w; |
||
234 | *height = h; |
||
235 | return stat; |
||
236 | } |
||
237 | |||
238 | |||
239 | /** |
||
240 | * Return the size of the window (or pixmap) that corresponds to the |
||
241 | * given XMesaBuffer. |
||
242 | * \param width returns width in pixels |
||
243 | * \param height returns height in pixels |
||
244 | */ |
||
245 | void |
||
246 | xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b, |
||
247 | GLuint *width, GLuint *height) |
||
248 | { |
||
249 | Status stat; |
||
250 | |||
251 | _glthread_LOCK_MUTEX(_xmesa_lock); |
||
252 | XSync(b->xm_visual->display, 0); /* added for Chromium */ |
||
253 | stat = get_drawable_size(dpy, b->frontxrb->pixmap, width, height); |
||
254 | _glthread_UNLOCK_MUTEX(_xmesa_lock); |
||
255 | |||
256 | if (!stat) { |
||
257 | /* probably querying a window that's recently been destroyed */ |
||
258 | _mesa_warning(NULL, "XGetGeometry failed!\n"); |
||
259 | *width = *height = 1; |
||
260 | } |
||
261 | } |
||
262 | |||
263 | |||
264 | |||
265 | /**********************************************************************/ |
||
266 | /***** Linked list of XMesaBuffers *****/ |
||
267 | /**********************************************************************/ |
||
268 | |||
269 | XMesaBuffer XMesaBufferList = NULL; |
||
270 | |||
271 | |||
272 | /** |
||
273 | * Allocate a new XMesaBuffer object which corresponds to the given drawable. |
||
274 | * Note that XMesaBuffer is derived from struct gl_framebuffer. |
||
275 | * The new XMesaBuffer will not have any size (Width=Height=0). |
||
276 | * |
||
277 | * \param d the corresponding X drawable (window or pixmap) |
||
278 | * \param type either WINDOW, PIXMAP or PBUFFER, describing d |
||
279 | * \param vis the buffer's visual |
||
280 | * \param cmap the window's colormap, if known. |
||
281 | * \return new XMesaBuffer or NULL if any problem |
||
282 | */ |
||
283 | static XMesaBuffer |
||
284 | create_xmesa_buffer(XMesaDrawable d, BufferType type, |
||
285 | XMesaVisual vis, XMesaColormap cmap) |
||
286 | { |
||
287 | XMesaBuffer b; |
||
288 | |||
289 | ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); |
||
290 | |||
291 | b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); |
||
292 | if (!b) |
||
293 | return NULL; |
||
294 | |||
295 | b->display = vis->display; |
||
296 | b->xm_visual = vis; |
||
297 | b->type = type; |
||
298 | b->cmap = cmap; |
||
299 | |||
300 | _mesa_initialize_window_framebuffer(&b->mesa_buffer, &vis->mesa_visual); |
||
301 | b->mesa_buffer.Delete = xmesa_delete_framebuffer; |
||
302 | |||
303 | /* |
||
304 | * Front renderbuffer |
||
305 | */ |
||
306 | b->frontxrb = xmesa_new_renderbuffer(NULL, 0, vis, GL_FALSE); |
||
307 | if (!b->frontxrb) { |
||
308 | free(b); |
||
309 | return NULL; |
||
310 | } |
||
311 | b->frontxrb->Parent = b; |
||
312 | b->frontxrb->drawable = d; |
||
313 | b->frontxrb->pixmap = (XMesaPixmap) d; |
||
314 | _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_FRONT_LEFT, |
||
315 | &b->frontxrb->Base.Base); |
||
316 | |||
317 | /* |
||
318 | * Back renderbuffer |
||
319 | */ |
||
320 | if (vis->mesa_visual.doubleBufferMode) { |
||
321 | b->backxrb = xmesa_new_renderbuffer(NULL, 0, vis, GL_TRUE); |
||
322 | if (!b->backxrb) { |
||
323 | /* XXX free front xrb too */ |
||
324 | free(b); |
||
325 | return NULL; |
||
326 | } |
||
327 | b->backxrb->Parent = b; |
||
328 | /* determine back buffer implementation */ |
||
329 | b->db_mode = vis->ximage_flag ? BACK_XIMAGE : BACK_PIXMAP; |
||
330 | |||
331 | _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_BACK_LEFT, |
||
332 | &b->backxrb->Base.Base); |
||
333 | } |
||
334 | |||
335 | /* |
||
336 | * Other renderbuffer (depth, stencil, etc) |
||
337 | */ |
||
338 | _swrast_add_soft_renderbuffers(&b->mesa_buffer, |
||
339 | GL_FALSE, /* color */ |
||
340 | vis->mesa_visual.haveDepthBuffer, |
||
341 | vis->mesa_visual.haveStencilBuffer, |
||
342 | vis->mesa_visual.haveAccumBuffer, |
||
343 | GL_FALSE, /* software alpha buffer */ |
||
344 | vis->mesa_visual.numAuxBuffers > 0 ); |
||
345 | |||
346 | /* GLX_EXT_texture_from_pixmap */ |
||
347 | b->TextureTarget = 0; |
||
348 | b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; |
||
349 | b->TextureMipmap = 0; |
||
350 | |||
351 | /* insert buffer into linked list */ |
||
352 | b->Next = XMesaBufferList; |
||
353 | XMesaBufferList = b; |
||
354 | |||
355 | return b; |
||
356 | } |
||
357 | |||
358 | |||
359 | /** |
||
360 | * Find an XMesaBuffer by matching X display and colormap but NOT matching |
||
361 | * the notThis buffer. |
||
362 | */ |
||
363 | XMesaBuffer |
||
364 | xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis) |
||
365 | { |
||
366 | XMesaBuffer b; |
||
367 | for (b=XMesaBufferList; b; b=b->Next) { |
||
368 | if (b->display==dpy && b->cmap==cmap && b!=notThis) { |
||
369 | return b; |
||
370 | } |
||
371 | } |
||
372 | return NULL; |
||
373 | } |
||
374 | |||
375 | |||
376 | /** |
||
377 | * Remove buffer from linked list, delete if no longer referenced. |
||
378 | */ |
||
379 | static void |
||
380 | xmesa_free_buffer(XMesaBuffer buffer) |
||
381 | { |
||
382 | XMesaBuffer prev = NULL, b; |
||
383 | |||
384 | for (b = XMesaBufferList; b; b = b->Next) { |
||
385 | if (b == buffer) { |
||
386 | struct gl_framebuffer *fb = &buffer->mesa_buffer; |
||
387 | |||
388 | /* unlink buffer from list */ |
||
389 | if (prev) |
||
390 | prev->Next = buffer->Next; |
||
391 | else |
||
392 | XMesaBufferList = buffer->Next; |
||
393 | |||
394 | /* mark as delete pending */ |
||
395 | fb->DeletePending = GL_TRUE; |
||
396 | |||
397 | /* Since the X window for the XMesaBuffer is going away, we don't |
||
398 | * want to dereference this pointer in the future. |
||
399 | */ |
||
400 | b->frontxrb->drawable = 0; |
||
401 | |||
402 | /* Unreference. If count = zero we'll really delete the buffer */ |
||
403 | _mesa_reference_framebuffer(&fb, NULL); |
||
404 | |||
405 | return; |
||
406 | } |
||
407 | /* continue search */ |
||
408 | prev = b; |
||
409 | } |
||
410 | /* buffer not found in XMesaBufferList */ |
||
411 | _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); |
||
412 | } |
||
413 | |||
414 | |||
415 | |||
416 | |||
417 | /**********************************************************************/ |
||
418 | /***** Misc Private Functions *****/ |
||
419 | /**********************************************************************/ |
||
420 | |||
421 | |||
422 | /** |
||
423 | * Setup RGB rendering for a window with a True/DirectColor visual. |
||
424 | */ |
||
425 | static void |
||
426 | setup_truecolor(XMesaVisual v, XMesaBuffer buffer, XMesaColormap cmap) |
||
427 | { |
||
428 | unsigned long rmask, gmask, bmask; |
||
429 | (void) buffer; |
||
430 | (void) cmap; |
||
431 | |||
432 | /* Compute red multiplier (mask) and bit shift */ |
||
433 | v->rshift = 0; |
||
434 | rmask = GET_REDMASK(v); |
||
435 | while ((rmask & 1)==0) { |
||
436 | v->rshift++; |
||
437 | rmask = rmask >> 1; |
||
438 | } |
||
439 | |||
440 | /* Compute green multiplier (mask) and bit shift */ |
||
441 | v->gshift = 0; |
||
442 | gmask = GET_GREENMASK(v); |
||
443 | while ((gmask & 1)==0) { |
||
444 | v->gshift++; |
||
445 | gmask = gmask >> 1; |
||
446 | } |
||
447 | |||
448 | /* Compute blue multiplier (mask) and bit shift */ |
||
449 | v->bshift = 0; |
||
450 | bmask = GET_BLUEMASK(v); |
||
451 | while ((bmask & 1)==0) { |
||
452 | v->bshift++; |
||
453 | bmask = bmask >> 1; |
||
454 | } |
||
455 | |||
456 | /* |
||
457 | * Compute component-to-pixel lookup tables and dithering kernel |
||
458 | */ |
||
459 | { |
||
460 | static GLubyte kernel[16] = { |
||
461 | 0*16, 8*16, 2*16, 10*16, |
||
462 | 12*16, 4*16, 14*16, 6*16, |
||
463 | 3*16, 11*16, 1*16, 9*16, |
||
464 | 15*16, 7*16, 13*16, 5*16, |
||
465 | }; |
||
466 | GLint rBits = _mesa_bitcount(rmask); |
||
467 | GLint gBits = _mesa_bitcount(gmask); |
||
468 | GLint bBits = _mesa_bitcount(bmask); |
||
469 | GLint maxBits; |
||
470 | GLuint i; |
||
471 | |||
472 | /* convert pixel components in [0,_mask] to RGB values in [0,255] */ |
||
473 | for (i=0; i<=rmask; i++) |
||
474 | v->PixelToR[i] = (unsigned char) ((i * 255) / rmask); |
||
475 | for (i=0; i<=gmask; i++) |
||
476 | v->PixelToG[i] = (unsigned char) ((i * 255) / gmask); |
||
477 | for (i=0; i<=bmask; i++) |
||
478 | v->PixelToB[i] = (unsigned char) ((i * 255) / bmask); |
||
479 | |||
480 | /* convert RGB values from [0,255] to pixel components */ |
||
481 | |||
482 | for (i=0;i<256;i++) { |
||
483 | GLint r = gamma_adjust(v->RedGamma, i, 255); |
||
484 | GLint g = gamma_adjust(v->GreenGamma, i, 255); |
||
485 | GLint b = gamma_adjust(v->BlueGamma, i, 255); |
||
486 | v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift; |
||
487 | v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift; |
||
488 | v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift; |
||
489 | } |
||
490 | /* overflow protection */ |
||
491 | for (i=256;i<512;i++) { |
||
492 | v->RtoPixel[i] = v->RtoPixel[255]; |
||
493 | v->GtoPixel[i] = v->GtoPixel[255]; |
||
494 | v->BtoPixel[i] = v->BtoPixel[255]; |
||
495 | } |
||
496 | |||
497 | /* setup dithering kernel */ |
||
498 | maxBits = rBits; |
||
499 | if (gBits > maxBits) maxBits = gBits; |
||
500 | if (bBits > maxBits) maxBits = bBits; |
||
501 | for (i=0;i<16;i++) { |
||
502 | v->Kernel[i] = kernel[i] >> maxBits; |
||
503 | } |
||
504 | |||
505 | v->undithered_pf = PF_Truecolor; |
||
506 | v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor; |
||
507 | } |
||
508 | |||
509 | /* |
||
510 | * Now check for TrueColor visuals which we can optimize. |
||
511 | */ |
||
512 | if ( GET_REDMASK(v) ==0x0000ff |
||
513 | && GET_GREENMASK(v)==0x00ff00 |
||
514 | && GET_BLUEMASK(v) ==0xff0000 |
||
515 | && CHECK_BYTE_ORDER(v) |
||
516 | && v->BitsPerPixel==32 |
||
517 | && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { |
||
518 | /* common 32 bpp config used on SGI, Sun */ |
||
519 | v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; /* ABGR */ |
||
520 | } |
||
521 | else if (GET_REDMASK(v) == 0xff0000 |
||
522 | && GET_GREENMASK(v)== 0x00ff00 |
||
523 | && GET_BLUEMASK(v) == 0x0000ff |
||
524 | && CHECK_BYTE_ORDER(v) |
||
525 | && v->RedGamma == 1.0 && v->GreenGamma == 1.0 && v->BlueGamma == 1.0){ |
||
526 | if (v->BitsPerPixel==32) { |
||
527 | /* if 32 bpp, and visual indicates 8 bpp alpha channel */ |
||
528 | if (GET_VISUAL_DEPTH(v) == 32 && v->mesa_visual.alphaBits == 8) |
||
529 | v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; /* ARGB */ |
||
530 | else |
||
531 | v->undithered_pf = v->dithered_pf = PF_8R8G8B; /* xRGB */ |
||
532 | } |
||
533 | else if (v->BitsPerPixel == 24) { |
||
534 | v->undithered_pf = v->dithered_pf = PF_8R8G8B24; /* RGB */ |
||
535 | } |
||
536 | } |
||
537 | else if (GET_REDMASK(v) ==0xf800 |
||
538 | && GET_GREENMASK(v)==0x07e0 |
||
539 | && GET_BLUEMASK(v) ==0x001f |
||
540 | && CHECK_BYTE_ORDER(v) |
||
541 | && v->BitsPerPixel==16 |
||
542 | && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { |
||
543 | /* 5-6-5 RGB */ |
||
544 | v->undithered_pf = PF_5R6G5B; |
||
545 | v->dithered_pf = PF_Dither_5R6G5B; |
||
546 | } |
||
547 | } |
||
548 | |||
549 | |||
550 | /** |
||
551 | * When a context is bound for the first time, we can finally finish |
||
552 | * initializing the context's visual and buffer information. |
||
553 | * \param v the XMesaVisual to initialize |
||
554 | * \param b the XMesaBuffer to initialize (may be NULL) |
||
555 | * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode |
||
556 | * \param window the window/pixmap we're rendering into |
||
557 | * \param cmap the colormap associated with the window/pixmap |
||
558 | * \return GL_TRUE=success, GL_FALSE=failure |
||
559 | */ |
||
560 | static GLboolean |
||
561 | initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, |
||
562 | XMesaDrawable window, |
||
563 | XMesaColormap cmap) |
||
564 | { |
||
565 | const int xclass = v->visualType; |
||
566 | |||
567 | |||
568 | ASSERT(!b || b->xm_visual == v); |
||
569 | |||
570 | /* Save true bits/pixel */ |
||
571 | v->BitsPerPixel = bits_per_pixel(v); |
||
572 | assert(v->BitsPerPixel > 0); |
||
573 | |||
574 | /* RGB WINDOW: |
||
575 | * We support RGB rendering into almost any kind of visual. |
||
576 | */ |
||
577 | if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { |
||
578 | setup_truecolor( v, b, cmap ); |
||
579 | } |
||
580 | else { |
||
581 | _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n"); |
||
582 | return GL_FALSE; |
||
583 | } |
||
584 | v->mesa_visual.indexBits = 0; |
||
585 | |||
586 | if (_mesa_getenv("MESA_NO_DITHER")) { |
||
587 | v->dithered_pf = v->undithered_pf; |
||
588 | } |
||
589 | |||
590 | |||
591 | /* |
||
592 | * If MESA_INFO env var is set print out some debugging info |
||
593 | * which can help Brian figure out what's going on when a user |
||
594 | * reports bugs. |
||
595 | */ |
||
596 | if (_mesa_getenv("MESA_INFO")) { |
||
597 | printf("X/Mesa visual = %p\n", (void *) v); |
||
598 | printf("X/Mesa dithered pf = %u\n", v->dithered_pf); |
||
599 | printf("X/Mesa undithered pf = %u\n", v->undithered_pf); |
||
600 | printf("X/Mesa level = %d\n", v->mesa_visual.level); |
||
601 | printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v)); |
||
602 | printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); |
||
603 | } |
||
604 | |||
605 | if (b && window) { |
||
606 | /* Do window-specific initializations */ |
||
607 | |||
608 | /* these should have been set in create_xmesa_buffer */ |
||
609 | ASSERT(b->frontxrb->drawable == window); |
||
610 | ASSERT(b->frontxrb->pixmap == (XMesaPixmap) window); |
||
611 | |||
612 | /* Setup for single/double buffering */ |
||
613 | if (v->mesa_visual.doubleBufferMode) { |
||
614 | /* Double buffered */ |
||
615 | b->shm = check_for_xshm( v->display ); |
||
616 | } |
||
617 | |||
618 | /* X11 graphics contexts */ |
||
619 | b->gc = XCreateGC( v->display, window, 0, NULL ); |
||
620 | XMesaSetFunction( v->display, b->gc, GXcopy ); |
||
621 | |||
622 | /* cleargc - for glClear() */ |
||
623 | b->cleargc = XCreateGC( v->display, window, 0, NULL ); |
||
624 | XMesaSetFunction( v->display, b->cleargc, GXcopy ); |
||
625 | |||
626 | /* |
||
627 | * Don't generate Graphics Expose/NoExpose events in swapbuffers(). |
||
628 | * Patch contributed by Michael Pichler May 15, 1995. |
||
629 | */ |
||
630 | { |
||
631 | XGCValues gcvalues; |
||
632 | gcvalues.graphics_exposures = False; |
||
633 | b->swapgc = XCreateGC(v->display, window, |
||
634 | GCGraphicsExposures, &gcvalues); |
||
635 | } |
||
636 | XMesaSetFunction( v->display, b->swapgc, GXcopy ); |
||
637 | } |
||
638 | |||
639 | return GL_TRUE; |
||
640 | } |
||
641 | |||
642 | |||
643 | |||
644 | /* |
||
645 | * Convert an RGBA color to a pixel value. |
||
646 | */ |
||
647 | unsigned long |
||
648 | xmesa_color_to_pixel(struct gl_context *ctx, |
||
649 | GLubyte r, GLubyte g, GLubyte b, GLubyte a, |
||
650 | GLuint pixelFormat) |
||
651 | { |
||
652 | XMesaContext xmesa = XMESA_CONTEXT(ctx); |
||
653 | switch (pixelFormat) { |
||
654 | case PF_Truecolor: |
||
655 | { |
||
656 | unsigned long p; |
||
657 | PACK_TRUECOLOR( p, r, g, b ); |
||
658 | return p; |
||
659 | } |
||
660 | case PF_8A8B8G8R: |
||
661 | return PACK_8A8B8G8R( r, g, b, a ); |
||
662 | case PF_8A8R8G8B: |
||
663 | return PACK_8A8R8G8B( r, g, b, a ); |
||
664 | case PF_8R8G8B: |
||
665 | /* fall through */ |
||
666 | case PF_8R8G8B24: |
||
667 | return PACK_8R8G8B( r, g, b ); |
||
668 | case PF_5R6G5B: |
||
669 | return PACK_5R6G5B( r, g, b ); |
||
670 | case PF_Dither_True: |
||
671 | /* fall through */ |
||
672 | case PF_Dither_5R6G5B: |
||
673 | { |
||
674 | unsigned long p; |
||
675 | PACK_TRUEDITHER(p, 1, 0, r, g, b); |
||
676 | return p; |
||
677 | } |
||
678 | default: |
||
679 | _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel"); |
||
680 | } |
||
681 | return 0; |
||
682 | } |
||
683 | |||
684 | |||
685 | #define NUM_VISUAL_TYPES 6 |
||
686 | |||
687 | /** |
||
688 | * Convert an X visual type to a GLX visual type. |
||
689 | * |
||
690 | * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) |
||
691 | * to be converted. |
||
692 | * \return If \c visualType is a valid X visual type, a GLX visual type will |
||
693 | * be returned. Otherwise \c GLX_NONE will be returned. |
||
694 | * |
||
695 | * \note |
||
696 | * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the |
||
697 | * DRI CVS tree. |
||
698 | */ |
||
699 | static GLint |
||
700 | xmesa_convert_from_x_visual_type( int visualType ) |
||
701 | { |
||
702 | static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { |
||
703 | GLX_STATIC_GRAY, GLX_GRAY_SCALE, |
||
704 | GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, |
||
705 | GLX_TRUE_COLOR, GLX_DIRECT_COLOR |
||
706 | }; |
||
707 | |||
708 | return ( (unsigned) visualType < NUM_VISUAL_TYPES ) |
||
709 | ? glx_visual_types[ visualType ] : GLX_NONE; |
||
710 | } |
||
711 | |||
712 | |||
713 | /**********************************************************************/ |
||
714 | /***** Public Functions *****/ |
||
715 | /**********************************************************************/ |
||
716 | |||
717 | |||
718 | /* |
||
719 | * Create a new X/Mesa visual. |
||
720 | * Input: display - X11 display |
||
721 | * visinfo - an XVisualInfo pointer |
||
722 | * rgb_flag - GL_TRUE = RGB mode, |
||
723 | * GL_FALSE = color index mode |
||
724 | * alpha_flag - alpha buffer requested? |
||
725 | * db_flag - GL_TRUE = double-buffered, |
||
726 | * GL_FALSE = single buffered |
||
727 | * stereo_flag - stereo visual? |
||
728 | * ximage_flag - GL_TRUE = use an XImage for back buffer, |
||
729 | * GL_FALSE = use an off-screen pixmap for back buffer |
||
730 | * depth_size - requested bits/depth values, or zero |
||
731 | * stencil_size - requested bits/stencil values, or zero |
||
732 | * accum_red_size - requested bits/red accum values, or zero |
||
733 | * accum_green_size - requested bits/green accum values, or zero |
||
734 | * accum_blue_size - requested bits/blue accum values, or zero |
||
735 | * accum_alpha_size - requested bits/alpha accum values, or zero |
||
736 | * num_samples - number of samples/pixel if multisampling, or zero |
||
737 | * level - visual level, usually 0 |
||
738 | * visualCaveat - ala the GLX extension, usually GLX_NONE |
||
739 | * Return; a new XMesaVisual or 0 if error. |
||
740 | */ |
||
741 | PUBLIC |
||
742 | XMesaVisual XMesaCreateVisual( XMesaDisplay *display, |
||
743 | XMesaVisualInfo visinfo, |
||
744 | GLboolean rgb_flag, |
||
745 | GLboolean alpha_flag, |
||
746 | GLboolean db_flag, |
||
747 | GLboolean stereo_flag, |
||
748 | GLboolean ximage_flag, |
||
749 | GLint depth_size, |
||
750 | GLint stencil_size, |
||
751 | GLint accum_red_size, |
||
752 | GLint accum_green_size, |
||
753 | GLint accum_blue_size, |
||
754 | GLint accum_alpha_size, |
||
755 | GLint num_samples, |
||
756 | GLint level, |
||
757 | GLint visualCaveat ) |
||
758 | { |
||
759 | char *gamma; |
||
760 | XMesaVisual v; |
||
761 | GLint red_bits, green_bits, blue_bits, alpha_bits; |
||
762 | |||
763 | /* For debugging only */ |
||
764 | if (_mesa_getenv("MESA_XSYNC")) { |
||
765 | /* This makes debugging X easier. |
||
766 | * In your debugger, set a breakpoint on _XError to stop when an |
||
767 | * X protocol error is generated. |
||
768 | */ |
||
769 | XSynchronize( display, 1 ); |
||
770 | } |
||
771 | |||
772 | /* Color-index rendering not supported. */ |
||
773 | if (!rgb_flag) |
||
774 | return NULL; |
||
775 | |||
776 | v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); |
||
777 | if (!v) { |
||
778 | return NULL; |
||
779 | } |
||
780 | |||
781 | v->display = display; |
||
782 | |||
783 | /* Save a copy of the XVisualInfo struct because the user may Xfree() |
||
784 | * the struct but we may need some of the information contained in it |
||
785 | * at a later time. |
||
786 | */ |
||
787 | v->visinfo = (XVisualInfo *) malloc(sizeof(*visinfo)); |
||
788 | if(!v->visinfo) { |
||
789 | free(v); |
||
790 | return NULL; |
||
791 | } |
||
792 | memcpy(v->visinfo, visinfo, sizeof(*visinfo)); |
||
793 | |||
794 | /* check for MESA_GAMMA environment variable */ |
||
795 | gamma = _mesa_getenv("MESA_GAMMA"); |
||
796 | if (gamma) { |
||
797 | v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; |
||
798 | sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); |
||
799 | if (v->RedGamma<=0.0) v->RedGamma = 1.0; |
||
800 | if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; |
||
801 | if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; |
||
802 | } |
||
803 | else { |
||
804 | v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; |
||
805 | } |
||
806 | |||
807 | v->ximage_flag = ximage_flag; |
||
808 | |||
809 | v->mesa_visual.redMask = visinfo->red_mask; |
||
810 | v->mesa_visual.greenMask = visinfo->green_mask; |
||
811 | v->mesa_visual.blueMask = visinfo->blue_mask; |
||
812 | v->visualID = visinfo->visualid; |
||
813 | v->screen = visinfo->screen; |
||
814 | |||
815 | #if !(defined(__cplusplus) || defined(c_plusplus)) |
||
816 | v->visualType = xmesa_convert_from_x_visual_type(visinfo->class); |
||
817 | #else |
||
818 | v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); |
||
819 | #endif |
||
820 | |||
821 | v->mesa_visual.visualRating = visualCaveat; |
||
822 | |||
823 | if (alpha_flag) |
||
824 | v->mesa_visual.alphaBits = 8; |
||
825 | |||
826 | (void) initialize_visual_and_buffer( v, NULL, 0, 0 ); |
||
827 | |||
828 | { |
||
829 | const int xclass = v->visualType; |
||
830 | if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { |
||
831 | red_bits = _mesa_bitcount(GET_REDMASK(v)); |
||
832 | green_bits = _mesa_bitcount(GET_GREENMASK(v)); |
||
833 | blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); |
||
834 | } |
||
835 | else { |
||
836 | /* this is an approximation */ |
||
837 | int depth; |
||
838 | depth = GET_VISUAL_DEPTH(v); |
||
839 | red_bits = depth / 3; |
||
840 | depth -= red_bits; |
||
841 | green_bits = depth / 2; |
||
842 | depth -= green_bits; |
||
843 | blue_bits = depth; |
||
844 | alpha_bits = 0; |
||
845 | assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); |
||
846 | } |
||
847 | alpha_bits = v->mesa_visual.alphaBits; |
||
848 | } |
||
849 | |||
850 | if (!_mesa_initialize_visual(&v->mesa_visual, |
||
851 | db_flag, stereo_flag, |
||
852 | red_bits, green_bits, |
||
853 | blue_bits, alpha_bits, |
||
854 | depth_size, |
||
855 | stencil_size, |
||
856 | accum_red_size, accum_green_size, |
||
857 | accum_blue_size, accum_alpha_size, |
||
858 | 0)) { |
||
859 | FREE(v); |
||
860 | return NULL; |
||
861 | } |
||
862 | |||
863 | /* XXX minor hack */ |
||
864 | v->mesa_visual.level = level; |
||
865 | return v; |
||
866 | } |
||
867 | |||
868 | |||
869 | PUBLIC |
||
870 | void XMesaDestroyVisual( XMesaVisual v ) |
||
871 | { |
||
872 | free(v->visinfo); |
||
873 | free(v); |
||
874 | } |
||
875 | |||
876 | |||
877 | |||
878 | /** |
||
879 | * Create a new XMesaContext. |
||
880 | * \param v the XMesaVisual |
||
881 | * \param share_list another XMesaContext with which to share display |
||
882 | * lists or NULL if no sharing is wanted. |
||
883 | * \return an XMesaContext or NULL if error. |
||
884 | */ |
||
885 | PUBLIC |
||
886 | XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) |
||
887 | { |
||
888 | static GLboolean firstTime = GL_TRUE; |
||
889 | XMesaContext c; |
||
890 | struct gl_context *mesaCtx; |
||
891 | struct dd_function_table functions; |
||
892 | TNLcontext *tnl; |
||
893 | |||
894 | if (firstTime) { |
||
895 | _glthread_INIT_MUTEX(_xmesa_lock); |
||
896 | firstTime = GL_FALSE; |
||
897 | } |
||
898 | |||
899 | /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */ |
||
900 | c = (XMesaContext) CALLOC_STRUCT(xmesa_context); |
||
901 | if (!c) |
||
902 | return NULL; |
||
903 | |||
904 | mesaCtx = &(c->mesa); |
||
905 | |||
906 | /* initialize with default driver functions, then plug in XMesa funcs */ |
||
907 | _mesa_init_driver_functions(&functions); |
||
908 | xmesa_init_driver_functions(v, &functions); |
||
909 | if (!_mesa_initialize_context(mesaCtx, API_OPENGL_COMPAT, &v->mesa_visual, |
||
910 | share_list ? &(share_list->mesa) : (struct gl_context *) NULL, |
||
911 | &functions)) { |
||
912 | free(c); |
||
913 | return NULL; |
||
914 | } |
||
915 | |||
916 | /* Enable this to exercise fixed function -> shader translation |
||
917 | * with software rendering. |
||
918 | */ |
||
919 | if (0) { |
||
920 | mesaCtx->VertexProgram._MaintainTnlProgram = GL_TRUE; |
||
921 | mesaCtx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; |
||
922 | } |
||
923 | |||
924 | _mesa_enable_sw_extensions(mesaCtx); |
||
925 | |||
926 | #if ENABLE_EXT_timer_query |
||
927 | mesaCtx->Extensions.EXT_timer_query = GL_TRUE; |
||
928 | #endif |
||
929 | |||
930 | |||
931 | /* finish up xmesa context initializations */ |
||
932 | c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE; |
||
933 | c->xm_visual = v; |
||
934 | c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ |
||
935 | c->display = v->display; |
||
936 | c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ |
||
937 | |||
938 | /* Initialize the software rasterizer and helper modules. |
||
939 | */ |
||
940 | if (!_swrast_CreateContext( mesaCtx ) || |
||
941 | !_vbo_CreateContext( mesaCtx ) || |
||
942 | !_tnl_CreateContext( mesaCtx ) || |
||
943 | !_swsetup_CreateContext( mesaCtx )) { |
||
944 | _mesa_free_context_data(&c->mesa); |
||
945 | free(c); |
||
946 | return NULL; |
||
947 | } |
||
948 | |||
949 | /* tnl setup */ |
||
950 | tnl = TNL_CONTEXT(mesaCtx); |
||
951 | tnl->Driver.RunPipeline = _tnl_run_pipeline; |
||
952 | /* swrast setup */ |
||
953 | xmesa_register_swrast_functions( mesaCtx ); |
||
954 | _swsetup_Wakeup(mesaCtx); |
||
955 | |||
956 | _mesa_meta_init(mesaCtx); |
||
957 | |||
958 | _mesa_compute_version(mesaCtx); |
||
959 | |||
960 | /* Exec table initialization requires the version to be computed */ |
||
961 | _mesa_initialize_dispatch_tables(mesaCtx); |
||
962 | _mesa_initialize_vbo_vtxfmt(mesaCtx); |
||
963 | |||
964 | return c; |
||
965 | } |
||
966 | |||
967 | |||
968 | |||
969 | PUBLIC |
||
970 | void XMesaDestroyContext( XMesaContext c ) |
||
971 | { |
||
972 | struct gl_context *mesaCtx = &c->mesa; |
||
973 | |||
974 | _mesa_meta_free( mesaCtx ); |
||
975 | |||
976 | _swsetup_DestroyContext( mesaCtx ); |
||
977 | _swrast_DestroyContext( mesaCtx ); |
||
978 | _tnl_DestroyContext( mesaCtx ); |
||
979 | _vbo_DestroyContext( mesaCtx ); |
||
980 | _mesa_free_context_data( mesaCtx ); |
||
981 | free( c ); |
||
982 | } |
||
983 | |||
984 | |||
985 | |||
986 | /** |
||
987 | * Private function for creating an XMesaBuffer which corresponds to an |
||
988 | * X window or pixmap. |
||
989 | * \param v the window's XMesaVisual |
||
990 | * \param w the window we're wrapping |
||
991 | * \return new XMesaBuffer or NULL if error |
||
992 | */ |
||
993 | PUBLIC XMesaBuffer |
||
994 | XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) |
||
995 | { |
||
996 | XWindowAttributes attr; |
||
997 | XMesaBuffer b; |
||
998 | XMesaColormap cmap; |
||
999 | int depth; |
||
1000 | |||
1001 | assert(v); |
||
1002 | assert(w); |
||
1003 | |||
1004 | /* Check that window depth matches visual depth */ |
||
1005 | XGetWindowAttributes( v->display, w, &attr ); |
||
1006 | depth = attr.depth; |
||
1007 | if (GET_VISUAL_DEPTH(v) != depth) { |
||
1008 | _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", |
||
1009 | GET_VISUAL_DEPTH(v), depth); |
||
1010 | return NULL; |
||
1011 | } |
||
1012 | |||
1013 | /* Find colormap */ |
||
1014 | if (attr.colormap) { |
||
1015 | cmap = attr.colormap; |
||
1016 | } |
||
1017 | else { |
||
1018 | _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); |
||
1019 | /* this is weird, a window w/out a colormap!? */ |
||
1020 | /* OK, let's just allocate a new one and hope for the best */ |
||
1021 | cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); |
||
1022 | } |
||
1023 | |||
1024 | b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap); |
||
1025 | if (!b) |
||
1026 | return NULL; |
||
1027 | |||
1028 | if (!initialize_visual_and_buffer( v, b, (XMesaDrawable) w, cmap )) { |
||
1029 | xmesa_free_buffer(b); |
||
1030 | return NULL; |
||
1031 | } |
||
1032 | |||
1033 | return b; |
||
1034 | } |
||
1035 | |||
1036 | |||
1037 | |||
1038 | /** |
||
1039 | * Create a new XMesaBuffer from an X pixmap. |
||
1040 | * |
||
1041 | * \param v the XMesaVisual |
||
1042 | * \param p the pixmap |
||
1043 | * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or |
||
1044 | * \c GLX_DIRECT_COLOR visual for the pixmap |
||
1045 | * \returns new XMesaBuffer or NULL if error |
||
1046 | */ |
||
1047 | PUBLIC XMesaBuffer |
||
1048 | XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap) |
||
1049 | { |
||
1050 | XMesaBuffer b; |
||
1051 | |||
1052 | assert(v); |
||
1053 | |||
1054 | b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); |
||
1055 | if (!b) |
||
1056 | return NULL; |
||
1057 | |||
1058 | if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) { |
||
1059 | xmesa_free_buffer(b); |
||
1060 | return NULL; |
||
1061 | } |
||
1062 | |||
1063 | return b; |
||
1064 | } |
||
1065 | |||
1066 | |||
1067 | /** |
||
1068 | * For GLX_EXT_texture_from_pixmap |
||
1069 | */ |
||
1070 | XMesaBuffer |
||
1071 | XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p, |
||
1072 | XMesaColormap cmap, |
||
1073 | int format, int target, int mipmap) |
||
1074 | { |
||
1075 | GET_CURRENT_CONTEXT(ctx); |
||
1076 | XMesaBuffer b; |
||
1077 | GLuint width, height; |
||
1078 | |||
1079 | assert(v); |
||
1080 | |||
1081 | b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); |
||
1082 | if (!b) |
||
1083 | return NULL; |
||
1084 | |||
1085 | /* get pixmap size, update framebuffer/renderbuffer dims */ |
||
1086 | xmesa_get_window_size(v->display, b, &width, &height); |
||
1087 | _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height); |
||
1088 | |||
1089 | if (target == 0) { |
||
1090 | /* examine dims */ |
||
1091 | if (ctx->Extensions.ARB_texture_non_power_of_two) { |
||
1092 | target = GLX_TEXTURE_2D_EXT; |
||
1093 | } |
||
1094 | else if ( _mesa_bitcount(width) == 1 |
||
1095 | && _mesa_bitcount(height) == 1) { |
||
1096 | /* power of two size */ |
||
1097 | if (height == 1) { |
||
1098 | target = GLX_TEXTURE_1D_EXT; |
||
1099 | } |
||
1100 | else { |
||
1101 | target = GLX_TEXTURE_2D_EXT; |
||
1102 | } |
||
1103 | } |
||
1104 | else if (ctx->Extensions.NV_texture_rectangle) { |
||
1105 | target = GLX_TEXTURE_RECTANGLE_EXT; |
||
1106 | } |
||
1107 | else { |
||
1108 | /* non power of two textures not supported */ |
||
1109 | XMesaDestroyBuffer(b); |
||
1110 | return 0; |
||
1111 | } |
||
1112 | } |
||
1113 | |||
1114 | b->TextureTarget = target; |
||
1115 | b->TextureFormat = format; |
||
1116 | b->TextureMipmap = mipmap; |
||
1117 | |||
1118 | if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) { |
||
1119 | xmesa_free_buffer(b); |
||
1120 | return NULL; |
||
1121 | } |
||
1122 | |||
1123 | return b; |
||
1124 | } |
||
1125 | |||
1126 | |||
1127 | |||
1128 | XMesaBuffer |
||
1129 | XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap, |
||
1130 | unsigned int width, unsigned int height) |
||
1131 | { |
||
1132 | XMesaWindow root; |
||
1133 | XMesaDrawable drawable; /* X Pixmap Drawable */ |
||
1134 | XMesaBuffer b; |
||
1135 | |||
1136 | /* allocate pixmap for front buffer */ |
||
1137 | root = RootWindow( v->display, v->visinfo->screen ); |
||
1138 | drawable = XCreatePixmap(v->display, root, width, height, |
||
1139 | v->visinfo->depth); |
||
1140 | if (!drawable) |
||
1141 | return NULL; |
||
1142 | |||
1143 | b = create_xmesa_buffer(drawable, PBUFFER, v, cmap); |
||
1144 | if (!b) |
||
1145 | return NULL; |
||
1146 | |||
1147 | if (!initialize_visual_and_buffer(v, b, drawable, cmap)) { |
||
1148 | xmesa_free_buffer(b); |
||
1149 | return NULL; |
||
1150 | } |
||
1151 | |||
1152 | return b; |
||
1153 | } |
||
1154 | |||
1155 | |||
1156 | |||
1157 | /* |
||
1158 | * Deallocate an XMesaBuffer structure and all related info. |
||
1159 | */ |
||
1160 | PUBLIC void |
||
1161 | XMesaDestroyBuffer(XMesaBuffer b) |
||
1162 | { |
||
1163 | xmesa_free_buffer(b); |
||
1164 | } |
||
1165 | |||
1166 | |||
1167 | /** |
||
1168 | * Query the current window size and update the corresponding struct gl_framebuffer |
||
1169 | * and all attached renderbuffers. |
||
1170 | * Called when: |
||
1171 | * 1. the first time a buffer is bound to a context. |
||
1172 | * 2. from glViewport to poll for window size changes |
||
1173 | * 3. from the XMesaResizeBuffers() API function. |
||
1174 | * Note: it's possible (and legal) for xmctx to be NULL. That can happen |
||
1175 | * when resizing a buffer when no rendering context is bound. |
||
1176 | */ |
||
1177 | void |
||
1178 | xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) |
||
1179 | { |
||
1180 | GLuint width, height; |
||
1181 | xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height); |
||
1182 | if (drawBuffer->mesa_buffer.Width != width || |
||
1183 | drawBuffer->mesa_buffer.Height != height) { |
||
1184 | struct gl_context *ctx = xmctx ? &xmctx->mesa : NULL; |
||
1185 | _mesa_resize_framebuffer(ctx, &(drawBuffer->mesa_buffer), width, height); |
||
1186 | } |
||
1187 | } |
||
1188 | |||
1189 | |||
1190 | /* |
||
1191 | * Bind buffer b to context c and make c the current rendering context. |
||
1192 | */ |
||
1193 | GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) |
||
1194 | { |
||
1195 | return XMesaMakeCurrent2( c, b, b ); |
||
1196 | } |
||
1197 | |||
1198 | |||
1199 | /* |
||
1200 | * Bind buffer b to context c and make c the current rendering context. |
||
1201 | */ |
||
1202 | PUBLIC |
||
1203 | GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, |
||
1204 | XMesaBuffer readBuffer ) |
||
1205 | { |
||
1206 | if (c) { |
||
1207 | if (!drawBuffer || !readBuffer) |
||
1208 | return GL_FALSE; /* must specify buffers! */ |
||
1209 | |||
1210 | if (&(c->mesa) == _mesa_get_current_context() |
||
1211 | && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer |
||
1212 | && c->mesa.ReadBuffer == &readBuffer->mesa_buffer |
||
1213 | && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) { |
||
1214 | /* same context and buffer, do nothing */ |
||
1215 | return GL_TRUE; |
||
1216 | } |
||
1217 | |||
1218 | c->xm_buffer = drawBuffer; |
||
1219 | |||
1220 | /* Call this periodically to detect when the user has begun using |
||
1221 | * GL rendering from multiple threads. |
||
1222 | */ |
||
1223 | _glapi_check_multithread(); |
||
1224 | |||
1225 | xmesa_check_and_update_buffer_size(c, drawBuffer); |
||
1226 | if (readBuffer != drawBuffer) |
||
1227 | xmesa_check_and_update_buffer_size(c, readBuffer); |
||
1228 | |||
1229 | _mesa_make_current(&(c->mesa), |
||
1230 | &drawBuffer->mesa_buffer, |
||
1231 | &readBuffer->mesa_buffer); |
||
1232 | |||
1233 | /* |
||
1234 | * Must recompute and set these pixel values because colormap |
||
1235 | * can be different for different windows. |
||
1236 | */ |
||
1237 | c->clearpixel = xmesa_color_to_pixel( &c->mesa, |
||
1238 | c->clearcolor[0], |
||
1239 | c->clearcolor[1], |
||
1240 | c->clearcolor[2], |
||
1241 | c->clearcolor[3], |
||
1242 | c->xm_visual->undithered_pf); |
||
1243 | XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel); |
||
1244 | |||
1245 | /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ |
||
1246 | drawBuffer->wasCurrent = GL_TRUE; |
||
1247 | } |
||
1248 | else { |
||
1249 | /* Detach */ |
||
1250 | _mesa_make_current( NULL, NULL, NULL ); |
||
1251 | } |
||
1252 | return GL_TRUE; |
||
1253 | } |
||
1254 | |||
1255 | |||
1256 | /* |
||
1257 | * Unbind the context c from its buffer. |
||
1258 | */ |
||
1259 | GLboolean XMesaUnbindContext( XMesaContext c ) |
||
1260 | { |
||
1261 | /* A no-op for XFree86 integration purposes */ |
||
1262 | return GL_TRUE; |
||
1263 | } |
||
1264 | |||
1265 | |||
1266 | XMesaContext XMesaGetCurrentContext( void ) |
||
1267 | { |
||
1268 | GET_CURRENT_CONTEXT(ctx); |
||
1269 | if (ctx) { |
||
1270 | XMesaContext xmesa = XMESA_CONTEXT(ctx); |
||
1271 | return xmesa; |
||
1272 | } |
||
1273 | else { |
||
1274 | return 0; |
||
1275 | } |
||
1276 | } |
||
1277 | |||
1278 | |||
1279 | XMesaBuffer XMesaGetCurrentBuffer( void ) |
||
1280 | { |
||
1281 | GET_CURRENT_CONTEXT(ctx); |
||
1282 | if (ctx) { |
||
1283 | XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); |
||
1284 | return xmbuf; |
||
1285 | } |
||
1286 | else { |
||
1287 | return 0; |
||
1288 | } |
||
1289 | } |
||
1290 | |||
1291 | |||
1292 | /* New in Mesa 3.1 */ |
||
1293 | XMesaBuffer XMesaGetCurrentReadBuffer( void ) |
||
1294 | { |
||
1295 | GET_CURRENT_CONTEXT(ctx); |
||
1296 | if (ctx) { |
||
1297 | return XMESA_BUFFER(ctx->ReadBuffer); |
||
1298 | } |
||
1299 | else { |
||
1300 | return 0; |
||
1301 | } |
||
1302 | } |
||
1303 | |||
1304 | |||
1305 | |||
1306 | GLboolean XMesaSetFXmode( GLint mode ) |
||
1307 | { |
||
1308 | (void) mode; |
||
1309 | return GL_FALSE; |
||
1310 | } |
||
1311 | |||
1312 | |||
1313 | |||
1314 | /* |
||
1315 | * Copy the back buffer to the front buffer. If there's no back buffer |
||
1316 | * this is a no-op. |
||
1317 | */ |
||
1318 | PUBLIC |
||
1319 | void XMesaSwapBuffers( XMesaBuffer b ) |
||
1320 | { |
||
1321 | GET_CURRENT_CONTEXT(ctx); |
||
1322 | |||
1323 | if (!b->backxrb) { |
||
1324 | /* single buffered */ |
||
1325 | return; |
||
1326 | } |
||
1327 | |||
1328 | /* If we're swapping the buffer associated with the current context |
||
1329 | * we have to flush any pending rendering commands first. |
||
1330 | */ |
||
1331 | if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) |
||
1332 | _mesa_notifySwapBuffers(ctx); |
||
1333 | |||
1334 | if (b->db_mode) { |
||
1335 | if (b->backxrb->ximage) { |
||
1336 | /* Copy Ximage (back buf) from client memory to server window */ |
||
1337 | #if defined(USE_XSHM) |
||
1338 | if (b->shm) { |
||
1339 | /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ |
||
1340 | XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, |
||
1341 | b->swapgc, |
||
1342 | b->backxrb->ximage, 0, 0, |
||
1343 | 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, |
||
1344 | False ); |
||
1345 | /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ |
||
1346 | } |
||
1347 | else |
||
1348 | #endif |
||
1349 | { |
||
1350 | /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ |
||
1351 | XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, |
||
1352 | b->swapgc, |
||
1353 | b->backxrb->ximage, 0, 0, |
||
1354 | 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height ); |
||
1355 | /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ |
||
1356 | } |
||
1357 | } |
||
1358 | else if (b->backxrb->pixmap) { |
||
1359 | /* Copy pixmap (back buf) to window (front buf) on server */ |
||
1360 | /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ |
||
1361 | XMesaCopyArea( b->xm_visual->display, |
||
1362 | b->backxrb->pixmap, /* source drawable */ |
||
1363 | b->frontxrb->drawable, /* dest. drawable */ |
||
1364 | b->swapgc, |
||
1365 | 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, |
||
1366 | 0, 0 /* dest region */ |
||
1367 | ); |
||
1368 | /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ |
||
1369 | } |
||
1370 | } |
||
1371 | XSync( b->xm_visual->display, False ); |
||
1372 | } |
||
1373 | |||
1374 | |||
1375 | |||
1376 | /* |
||
1377 | * Copy sub-region of back buffer to front buffer |
||
1378 | */ |
||
1379 | void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) |
||
1380 | { |
||
1381 | GET_CURRENT_CONTEXT(ctx); |
||
1382 | |||
1383 | /* If we're swapping the buffer associated with the current context |
||
1384 | * we have to flush any pending rendering commands first. |
||
1385 | */ |
||
1386 | if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) |
||
1387 | _mesa_notifySwapBuffers(ctx); |
||
1388 | |||
1389 | if (!b->backxrb) { |
||
1390 | /* single buffered */ |
||
1391 | return; |
||
1392 | } |
||
1393 | |||
1394 | if (b->db_mode) { |
||
1395 | int yTop = b->mesa_buffer.Height - y - height; |
||
1396 | if (b->backxrb->ximage) { |
||
1397 | /* Copy Ximage from host's memory to server's window */ |
||
1398 | #if defined(USE_XSHM) |
||
1399 | if (b->shm) { |
||
1400 | /* XXX assuming width and height aren't too large! */ |
||
1401 | XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, |
||
1402 | b->swapgc, |
||
1403 | b->backxrb->ximage, x, yTop, |
||
1404 | x, yTop, width, height, False ); |
||
1405 | /* wait for finished event??? */ |
||
1406 | } |
||
1407 | else |
||
1408 | #endif |
||
1409 | { |
||
1410 | /* XXX assuming width and height aren't too large! */ |
||
1411 | XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, |
||
1412 | b->swapgc, |
||
1413 | b->backxrb->ximage, x, yTop, |
||
1414 | x, yTop, width, height ); |
||
1415 | } |
||
1416 | } |
||
1417 | else { |
||
1418 | /* Copy pixmap to window on server */ |
||
1419 | XMesaCopyArea( b->xm_visual->display, |
||
1420 | b->backxrb->pixmap, /* source drawable */ |
||
1421 | b->frontxrb->drawable, /* dest. drawable */ |
||
1422 | b->swapgc, |
||
1423 | x, yTop, width, height, /* source region */ |
||
1424 | x, yTop /* dest region */ |
||
1425 | ); |
||
1426 | } |
||
1427 | } |
||
1428 | } |
||
1429 | |||
1430 | |||
1431 | /* |
||
1432 | * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function |
||
1433 | * is a way to get "under the hood" of X/Mesa so one can manipulate the |
||
1434 | * back buffer directly. |
||
1435 | * Output: pixmap - pointer to back buffer's Pixmap, or 0 |
||
1436 | * ximage - pointer to back buffer's XImage, or NULL |
||
1437 | * Return: GL_TRUE = context is double buffered |
||
1438 | * GL_FALSE = context is single buffered |
||
1439 | */ |
||
1440 | GLboolean XMesaGetBackBuffer( XMesaBuffer b, |
||
1441 | XMesaPixmap *pixmap, |
||
1442 | XMesaImage **ximage ) |
||
1443 | { |
||
1444 | if (b->db_mode) { |
||
1445 | if (pixmap) |
||
1446 | *pixmap = b->backxrb->pixmap; |
||
1447 | if (ximage) |
||
1448 | *ximage = b->backxrb->ximage; |
||
1449 | return GL_TRUE; |
||
1450 | } |
||
1451 | else { |
||
1452 | *pixmap = 0; |
||
1453 | *ximage = NULL; |
||
1454 | return GL_FALSE; |
||
1455 | } |
||
1456 | } |
||
1457 | |||
1458 | |||
1459 | /* |
||
1460 | * Return the depth buffer associated with an XMesaBuffer. |
||
1461 | * Input: b - the XMesa buffer handle |
||
1462 | * Output: width, height - size of buffer in pixels |
||
1463 | * bytesPerValue - bytes per depth value (2 or 4) |
||
1464 | * buffer - pointer to depth buffer values |
||
1465 | * Return: GL_TRUE or GL_FALSE to indicate success or failure. |
||
1466 | */ |
||
1467 | GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, |
||
1468 | GLint *bytesPerValue, void **buffer ) |
||
1469 | { |
||
1470 | struct gl_renderbuffer *rb |
||
1471 | = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer; |
||
1472 | struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); |
||
1473 | |||
1474 | if (!xrb || !xrb->Base.Buffer) { |
||
1475 | *width = 0; |
||
1476 | *height = 0; |
||
1477 | *bytesPerValue = 0; |
||
1478 | *buffer = 0; |
||
1479 | return GL_FALSE; |
||
1480 | } |
||
1481 | else { |
||
1482 | *width = b->mesa_buffer.Width; |
||
1483 | *height = b->mesa_buffer.Height; |
||
1484 | *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16 |
||
1485 | ? sizeof(GLushort) : sizeof(GLuint); |
||
1486 | *buffer = (void *) xrb->Base.Buffer; |
||
1487 | return GL_TRUE; |
||
1488 | } |
||
1489 | } |
||
1490 | |||
1491 | |||
1492 | void XMesaFlush( XMesaContext c ) |
||
1493 | { |
||
1494 | if (c && c->xm_visual) { |
||
1495 | XSync( c->xm_visual->display, False ); |
||
1496 | } |
||
1497 | } |
||
1498 | |||
1499 | |||
1500 | |||
1501 | const char *XMesaGetString( XMesaContext c, int name ) |
||
1502 | { |
||
1503 | (void) c; |
||
1504 | if (name==XMESA_VERSION) { |
||
1505 | return "5.0"; |
||
1506 | } |
||
1507 | else if (name==XMESA_EXTENSIONS) { |
||
1508 | return ""; |
||
1509 | } |
||
1510 | else { |
||
1511 | return NULL; |
||
1512 | } |
||
1513 | } |
||
1514 | |||
1515 | |||
1516 | |||
1517 | XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) |
||
1518 | { |
||
1519 | XMesaBuffer b; |
||
1520 | for (b=XMesaBufferList; b; b=b->Next) { |
||
1521 | if (b->frontxrb->drawable == d && b->display == dpy) { |
||
1522 | return b; |
||
1523 | } |
||
1524 | } |
||
1525 | return NULL; |
||
1526 | } |
||
1527 | |||
1528 | |||
1529 | /** |
||
1530 | * Free/destroy all XMesaBuffers associated with given display. |
||
1531 | */ |
||
1532 | void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy) |
||
1533 | { |
||
1534 | XMesaBuffer b, next; |
||
1535 | for (b = XMesaBufferList; b; b = next) { |
||
1536 | next = b->Next; |
||
1537 | if (b->display == dpy) { |
||
1538 | xmesa_free_buffer(b); |
||
1539 | } |
||
1540 | } |
||
1541 | } |
||
1542 | |||
1543 | |||
1544 | /* |
||
1545 | * Look for XMesaBuffers whose X window has been destroyed. |
||
1546 | * Deallocate any such XMesaBuffers. |
||
1547 | */ |
||
1548 | void XMesaGarbageCollect( XMesaDisplay* dpy ) |
||
1549 | { |
||
1550 | XMesaBuffer b, next; |
||
1551 | for (b=XMesaBufferList; b; b=next) { |
||
1552 | next = b->Next; |
||
1553 | if (b->display && b->display == dpy && b->frontxrb->drawable && b->type == WINDOW) { |
||
1554 | XSync(b->display, False); |
||
1555 | if (!window_exists( b->display, b->frontxrb->drawable )) { |
||
1556 | /* found a dead window, free the ancillary info */ |
||
1557 | XMesaDestroyBuffer( b ); |
||
1558 | } |
||
1559 | } |
||
1560 | } |
||
1561 | } |
||
1562 | |||
1563 | |||
1564 | unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, |
||
1565 | GLfloat red, GLfloat green, |
||
1566 | GLfloat blue, GLfloat alpha ) |
||
1567 | { |
||
1568 | GLint r = (GLint) (red * 255.0F); |
||
1569 | GLint g = (GLint) (green * 255.0F); |
||
1570 | GLint b = (GLint) (blue * 255.0F); |
||
1571 | GLint a = (GLint) (alpha * 255.0F); |
||
1572 | |||
1573 | switch (xmesa->pixelformat) { |
||
1574 | case PF_Truecolor: |
||
1575 | { |
||
1576 | unsigned long p; |
||
1577 | PACK_TRUECOLOR( p, r, g, b ); |
||
1578 | return p; |
||
1579 | } |
||
1580 | case PF_8A8B8G8R: |
||
1581 | return PACK_8A8B8G8R( r, g, b, a ); |
||
1582 | case PF_8A8R8G8B: |
||
1583 | return PACK_8A8R8G8B( r, g, b, a ); |
||
1584 | case PF_8R8G8B: |
||
1585 | return PACK_8R8G8B( r, g, b ); |
||
1586 | case PF_5R6G5B: |
||
1587 | return PACK_5R6G5B( r, g, b ); |
||
1588 | case PF_Dither_5R6G5B: |
||
1589 | /* fall through */ |
||
1590 | case PF_Dither_True: |
||
1591 | { |
||
1592 | unsigned long p; |
||
1593 | PACK_TRUEDITHER(p, x, y, r, g, b); |
||
1594 | return p; |
||
1595 | } |
||
1596 | default: |
||
1597 | _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); |
||
1598 | } |
||
1599 | return 0; |
||
1600 | } |
||
1601 | |||
1602 | |||
1603 | /* |
||
1604 | * This is typically called when the window size changes and we need |
||
1605 | * to reallocate the buffer's back/depth/stencil/accum buffers. |
||
1606 | */ |
||
1607 | PUBLIC void |
||
1608 | XMesaResizeBuffers( XMesaBuffer b ) |
||
1609 | { |
||
1610 | GET_CURRENT_CONTEXT(ctx); |
||
1611 | XMesaContext xmctx = XMESA_CONTEXT(ctx); |
||
1612 | if (!xmctx) |
||
1613 | return; |
||
1614 | xmesa_check_and_update_buffer_size(xmctx, b); |
||
1615 | } |
||
1616 | |||
1617 | |||
1618 | static GLint |
||
1619 | xbuffer_to_renderbuffer(int buffer) |
||
1620 | { |
||
1621 | assert(MAX_AUX_BUFFERS <= 4); |
||
1622 | |||
1623 | switch (buffer) { |
||
1624 | case GLX_FRONT_LEFT_EXT: |
||
1625 | return BUFFER_FRONT_LEFT; |
||
1626 | case GLX_FRONT_RIGHT_EXT: |
||
1627 | return BUFFER_FRONT_RIGHT; |
||
1628 | case GLX_BACK_LEFT_EXT: |
||
1629 | return BUFFER_BACK_LEFT; |
||
1630 | case GLX_BACK_RIGHT_EXT: |
||
1631 | return BUFFER_BACK_RIGHT; |
||
1632 | case GLX_AUX0_EXT: |
||
1633 | return BUFFER_AUX0; |
||
1634 | case GLX_AUX1_EXT: |
||
1635 | case GLX_AUX2_EXT: |
||
1636 | case GLX_AUX3_EXT: |
||
1637 | case GLX_AUX4_EXT: |
||
1638 | case GLX_AUX5_EXT: |
||
1639 | case GLX_AUX6_EXT: |
||
1640 | case GLX_AUX7_EXT: |
||
1641 | case GLX_AUX8_EXT: |
||
1642 | case GLX_AUX9_EXT: |
||
1643 | default: |
||
1644 | /* BadValue error */ |
||
1645 | return -1; |
||
1646 | } |
||
1647 | } |
||
1648 | |||
1649 | |||
1650 | PUBLIC void |
||
1651 | XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer, |
||
1652 | const int *attrib_list) |
||
1653 | { |
||
1654 | #if 0 |
||
1655 | GET_CURRENT_CONTEXT(ctx); |
||
1656 | const GLuint unit = ctx->Texture.CurrentUnit; |
||
1657 | struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
||
1658 | struct gl_texture_object *texObj; |
||
1659 | #endif |
||
1660 | struct gl_renderbuffer *rb; |
||
1661 | struct xmesa_renderbuffer *xrb; |
||
1662 | GLint b; |
||
1663 | XMesaImage *img = NULL; |
||
1664 | GLboolean freeImg = GL_FALSE; |
||
1665 | |||
1666 | b = xbuffer_to_renderbuffer(buffer); |
||
1667 | if (b < 0) |
||
1668 | return; |
||
1669 | |||
1670 | if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT) |
||
1671 | return; /* BadMatch error */ |
||
1672 | |||
1673 | rb = drawable->mesa_buffer.Attachment[b].Renderbuffer; |
||
1674 | if (!rb) { |
||
1675 | /* invalid buffer */ |
||
1676 | return; |
||
1677 | } |
||
1678 | xrb = xmesa_renderbuffer(rb); |
||
1679 | |||
1680 | #if 0 |
||
1681 | switch (drawable->TextureTarget) { |
||
1682 | case GLX_TEXTURE_1D_EXT: |
||
1683 | texObj = texUnit->CurrentTex[TEXTURE_1D_INDEX]; |
||
1684 | break; |
||
1685 | case GLX_TEXTURE_2D_EXT: |
||
1686 | texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX]; |
||
1687 | break; |
||
1688 | case GLX_TEXTURE_RECTANGLE_EXT: |
||
1689 | texObj = texUnit->CurrentTex[TEXTURE_RECT_INDEX]; |
||
1690 | break; |
||
1691 | default: |
||
1692 | return; /* BadMatch error */ |
||
1693 | } |
||
1694 | #endif |
||
1695 | |||
1696 | /* |
||
1697 | * The following is a quick and simple way to implement |
||
1698 | * BindTexImage. The better way is to write some new FetchTexel() |
||
1699 | * functions which would extract texels from XImages. We'd still |
||
1700 | * need to use GetImage when texturing from a Pixmap (front buffer) |
||
1701 | * but texturing from a back buffer (XImage) would avoid an image |
||
1702 | * copy. |
||
1703 | */ |
||
1704 | |||
1705 | /* get XImage */ |
||
1706 | if (xrb->pixmap) { |
||
1707 | img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L, |
||
1708 | ZPixmap); |
||
1709 | freeImg = GL_TRUE; |
||
1710 | } |
||
1711 | else if (xrb->ximage) { |
||
1712 | img = xrb->ximage; |
||
1713 | } |
||
1714 | |||
1715 | /* store the XImage as a new texture image */ |
||
1716 | if (img) { |
||
1717 | GLenum format, type, intFormat; |
||
1718 | if (img->bits_per_pixel == 32) { |
||
1719 | format = GL_BGRA; |
||
1720 | type = GL_UNSIGNED_BYTE; |
||
1721 | intFormat = GL_RGBA; |
||
1722 | } |
||
1723 | else if (img->bits_per_pixel == 24) { |
||
1724 | format = GL_BGR; |
||
1725 | type = GL_UNSIGNED_BYTE; |
||
1726 | intFormat = GL_RGB; |
||
1727 | } |
||
1728 | else if (img->bits_per_pixel == 16) { |
||
1729 | format = GL_BGR; |
||
1730 | type = GL_UNSIGNED_SHORT_5_6_5; |
||
1731 | intFormat = GL_RGB; |
||
1732 | } |
||
1733 | else { |
||
1734 | _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage"); |
||
1735 | return; |
||
1736 | } |
||
1737 | if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) { |
||
1738 | intFormat = GL_RGBA; |
||
1739 | } |
||
1740 | else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) { |
||
1741 | intFormat = GL_RGB; |
||
1742 | } |
||
1743 | |||
1744 | _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0, |
||
1745 | format, type, img->data); |
||
1746 | |||
1747 | if (freeImg) { |
||
1748 | XMesaDestroyImage(img); |
||
1749 | } |
||
1750 | } |
||
1751 | } |
||
1752 | |||
1753 | |||
1754 | |||
1755 | PUBLIC void |
||
1756 | XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer) |
||
1757 | { |
||
1758 | const GLint b = xbuffer_to_renderbuffer(buffer); |
||
1759 | if (b < 0) |
||
1760 | return; |
||
1761 | |||
1762 | /* no-op for now */ |
||
1763 | }>>=>=>=0.0)>=0.0)>=0.0)>>24)>16;i++)>512;i++)>><>><>><>256;i++)>=bmask;>=gmask;>=rmask;> |
||
1764 |