2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * General device driver functions for Xlib driver.
31 #include "glxheader.h"
32 #include "bufferobj.h"
38 #include "extensions.h"
39 #include "framebuffer.h"
48 #include "texformat.h"
51 #include "pipe/softpipe/sp_context.h"
52 #include "state_tracker/st_public.h"
53 #include "state_tracker/st_context.h"
54 #include "state_tracker/st_draw.h"
58 * Dithering kernels and lookup tables.
61 const int xmesa_kernel8
[DITH_DY
* DITH_DX
] = {
62 0 * MAXC
, 8 * MAXC
, 2 * MAXC
, 10 * MAXC
,
63 12 * MAXC
, 4 * MAXC
, 14 * MAXC
, 6 * MAXC
,
64 3 * MAXC
, 11 * MAXC
, 1 * MAXC
, 9 * MAXC
,
65 15 * MAXC
, 7 * MAXC
, 13 * MAXC
, 5 * MAXC
,
68 const short xmesa_HPCR_DRGB
[3][2][16] = {
70 { 16, -4, 1,-11, 14, -6, 3, -9, 15, -5, 2,-10, 13, -7, 4, -8},
71 {-15, 5, 0, 12,-13, 7, -2, 10,-14, 6, -1, 11,-12, 8, -3, 9}
74 {-11, 15, -7, 3, -8, 14, -4, 2,-10, 16, -6, 4, -9, 13, -5, 1},
75 { 12,-14, 8, -2, 9,-13, 5, -1, 11,-15, 7, -3, 10,-12, 6, 0}
78 { 6,-18, 26,-14, 2,-22, 30,-10, 8,-16, 28,-12, 4,-20, 32, -8},
79 { -4, 20,-24, 16, 0, 24,-28, 12, -6, 18,-26, 14, -2, 22,-30, 10}
83 const int xmesa_kernel1
[16] = {
84 0*47, 9*47, 4*47, 12*47, /* 47 = (255*3)/16 */
85 6*47, 2*47, 14*47, 8*47,
86 10*47, 1*47, 5*47, 11*47,
87 7*47, 13*47, 3*47, 15*47
92 finish_or_flush( GLcontext
*ctx
)
97 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
99 _glthread_LOCK_MUTEX(_xmesa_lock
);
100 XSync( xmesa
->display
, False
);
101 _glthread_UNLOCK_MUTEX(_xmesa_lock
);
108 /**********************************************************************/
109 /*** glClear implementations ***/
110 /**********************************************************************/
114 * Clear the front or back color buffer, if it's implemented with a pixmap.
117 clear_pixmap(GLcontext
*ctx
, struct xmesa_renderbuffer
*xrb
, GLuint value
)
119 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
120 XMesaBuffer xmbuf
= XMESA_BUFFER(ctx
->DrawBuffer
);
125 assert(xmesa
->display
);
127 assert(xmbuf
->cleargc
);
129 XMesaSetForeground( xmesa
->display
, xmbuf
->cleargc
, value
);
131 XMesaFillRectangle( xmesa
->display
, xrb
->pixmap
, xmbuf
->cleargc
,
132 0, 0, xrb
->St
.Base
.Width
, xrb
->St
.Base
.Height
);
137 clear_8bit_ximage(GLcontext
*ctx
, struct xmesa_renderbuffer
*xrb
, GLuint value
)
139 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
140 GLint width
= xrb
->St
.Base
.Width
;
141 GLint height
= xrb
->St
.Base
.Height
;
143 for (i
= 0; i
< height
; i
++) {
144 GLubyte
*ptr
= PIXEL_ADDR1(xrb
, 0, i
);
145 MEMSET( ptr
, xmesa
->clearpixel
, width
);
151 clear_HPCR_ximage(GLcontext
*ctx
, struct xmesa_renderbuffer
*xrb
, GLuint value
)
154 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
155 GLint width
= xrb
->St
.Base
.Width
;
156 GLint height
= xrb
->St
.Base
.Height
;
158 for (i
= 0; i
< height
; i
++) {
159 GLubyte
*ptr
= PIXEL_ADDR1( xrb
, 0, i
);
161 const GLubyte
*sptr
= xmesa
->xm_visual
->hpcr_clear_ximage_pattern
[0];
165 for (j
= 0; j
< width
; j
++) {
174 clear_16bit_ximage(GLcontext
*ctx
, struct xmesa_renderbuffer
*xrb
, GLuint value
)
176 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
177 GLint width
= xrb
->St
.Base
.Width
;
178 GLint height
= xrb
->St
.Base
.Height
;
181 if (xmesa
->swapbytes
) {
182 value
= ((value
>> 8) & 0x00ff) | ((value
<< 8) & 0xff00);
185 for (j
= 0; j
< height
; j
++) {
186 GLushort
*ptr2
= PIXEL_ADDR2(xrb
, 0, j
);
187 for (i
= 0; i
< width
; i
++) {
194 /* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
196 clear_24bit_ximage(GLcontext
*ctx
, struct xmesa_renderbuffer
*xrb
,
199 GLint width
= xrb
->St
.Base
.Width
;
200 GLint height
= xrb
->St
.Base
.Height
;
201 const GLubyte r
= (value
) & 0xff;
202 const GLubyte g
= (value
>> 8) & 0xff;
203 const GLubyte b
= (value
>> 16) & 0xff;
205 if (r
== g
&& g
== b
) {
206 /* same value for all three components (gray) */
208 for (j
= 0; j
< height
; j
++) {
209 bgr_t
*ptr3
= PIXEL_ADDR3(xrb
, 0, j
);
210 MEMSET(ptr3
, r
, 3 * width
);
214 /* non-gray clear color */
216 for (j
= 0; j
< height
; j
++) {
217 bgr_t
*ptr3
= PIXEL_ADDR3(xrb
, 0, j
);
218 for (i
= 0; i
< width
; i
++) {
230 clear_32bit_ximage(GLcontext
*ctx
, struct xmesa_renderbuffer
*xrb
,
233 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
234 GLint width
= xrb
->St
.Base
.Width
;
235 GLint height
= xrb
->St
.Base
.Height
;
236 const GLuint n
= width
* height
;
237 GLuint
*ptr4
= (GLuint
*) xrb
->ximage
->data
;
242 if (xmesa
->swapbytes
) {
243 value
= ((value
>> 24) & 0x000000ff)
244 | ((value
>> 8) & 0x0000ff00)
245 | ((value
<< 8) & 0x00ff0000)
246 | ((value
<< 24) & 0xff000000);
251 _mesa_memset(ptr4
, value
, 4 * n
);
255 for (i
= 0; i
< n
; i
++)
262 clear_nbit_ximage(GLcontext
*ctx
, struct xmesa_renderbuffer
*xrb
, GLuint value
)
264 XMesaImage
*img
= xrb
->ximage
;
265 GLint width
= xrb
->St
.Base
.Width
;
266 GLint height
= xrb
->St
.Base
.Height
;
268 for (j
= 0; j
< height
; j
++) {
269 for (i
= 0; i
< width
; i
++) {
270 XMesaPutPixel(img
, i
, j
, value
);
278 xmesa_clear_buffers(GLcontext
*ctx
, GLbitfield buffers
, GLuint value
)
280 if (ctx
->DrawBuffer
->Name
== 0) {
281 /* this is a window system framebuffer */
282 const GLuint
*colorMask
= (GLuint
*) &ctx
->Color
.ColorMask
;
283 XMesaBuffer b
= XMESA_BUFFER(ctx
->DrawBuffer
);
285 /* we can't handle color or index masking */
286 if (*colorMask
== 0xffffffff && ctx
->Color
.IndexMask
== 0xffffffff) {
287 if (buffers
& BUFFER_BIT_FRONT_LEFT
) {
288 /* clear front color buffer */
289 struct gl_renderbuffer
*frontRb
290 = ctx
->DrawBuffer
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
291 if (b
->frontxrb
== xmesa_renderbuffer(frontRb
)) {
292 /* renderbuffer is not wrapped - great! */
293 b
->frontxrb
->clearFunc(ctx
, b
->frontxrb
, value
);
294 buffers
&= ~BUFFER_BIT_FRONT_LEFT
;
297 /* we can't directly clear an alpha-wrapped color buffer */
300 if (buffers
& BUFFER_BIT_BACK_LEFT
) {
301 /* clear back color buffer */
302 struct gl_renderbuffer
*backRb
303 = ctx
->DrawBuffer
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
304 if (b
->backxrb
== xmesa_renderbuffer(backRb
)) {
305 /* renderbuffer is not wrapped - great! */
306 b
->backxrb
->clearFunc(ctx
, b
->backxrb
, value
);
307 buffers
&= ~BUFFER_BIT_BACK_LEFT
;
316 clear_color_HPCR_ximage( GLcontext
*ctx
, const GLfloat color
[4] )
319 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
321 CLAMPED_FLOAT_TO_UBYTE(xmesa
->clearcolor
[0], color
[0]);
322 CLAMPED_FLOAT_TO_UBYTE(xmesa
->clearcolor
[1], color
[1]);
323 CLAMPED_FLOAT_TO_UBYTE(xmesa
->clearcolor
[2], color
[2]);
324 CLAMPED_FLOAT_TO_UBYTE(xmesa
->clearcolor
[3], color
[3]);
326 if (color
[0] == 0.0 && color
[1] == 0.0 && color
[2] == 0.0) {
328 MEMSET( xmesa
->xm_visual
->hpcr_clear_ximage_pattern
, 0x0 ,
329 sizeof(xmesa
->xm_visual
->hpcr_clear_ximage_pattern
));
332 /* build clear pattern */
333 for (i
=0; i
<16; i
++) {
334 xmesa
->xm_visual
->hpcr_clear_ximage_pattern
[0][i
] =
336 xmesa
->clearcolor
[0],
337 xmesa
->clearcolor
[1],
338 xmesa
->clearcolor
[2]);
339 xmesa
->xm_visual
->hpcr_clear_ximage_pattern
[1][i
] =
341 xmesa
->clearcolor
[0],
342 xmesa
->clearcolor
[1],
343 xmesa
->clearcolor
[2]);
350 clear_color_HPCR_pixmap( GLcontext
*ctx
, const GLfloat color
[4] )
353 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
355 CLAMPED_FLOAT_TO_UBYTE(xmesa
->clearcolor
[0], color
[0]);
356 CLAMPED_FLOAT_TO_UBYTE(xmesa
->clearcolor
[1], color
[1]);
357 CLAMPED_FLOAT_TO_UBYTE(xmesa
->clearcolor
[2], color
[2]);
358 CLAMPED_FLOAT_TO_UBYTE(xmesa
->clearcolor
[3], color
[3]);
360 if (color
[0] == 0.0 && color
[1] == 0.0 && color
[2] == 0.0) {
362 for (i
=0; i
<16; i
++) {
363 XMesaPutPixel(xmesa
->xm_visual
->hpcr_clear_ximage
, i
, 0, 0);
364 XMesaPutPixel(xmesa
->xm_visual
->hpcr_clear_ximage
, i
, 1, 0);
368 for (i
=0; i
<16; i
++) {
369 XMesaPutPixel(xmesa
->xm_visual
->hpcr_clear_ximage
, i
, 0,
371 xmesa
->clearcolor
[0],
372 xmesa
->clearcolor
[1],
373 xmesa
->clearcolor
[2]));
374 XMesaPutPixel(xmesa
->xm_visual
->hpcr_clear_ximage
, i
, 1,
376 xmesa
->clearcolor
[0],
377 xmesa
->clearcolor
[1],
378 xmesa
->clearcolor
[2]));
381 /* change tile pixmap content */
382 XMesaPutImage(xmesa
->display
,
383 (XMesaDrawable
)xmesa
->xm_visual
->hpcr_clear_pixmap
,
384 XMESA_BUFFER(ctx
->DrawBuffer
)->cleargc
,
385 xmesa
->xm_visual
->hpcr_clear_ximage
, 0, 0, 0, 0, 16, 2);
390 * Called when the driver should update its state, based on the new_state
394 xmesa_update_state( GLcontext
*ctx
, GLbitfield new_state
)
396 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
398 st_invalidate_state( ctx
, new_state
);
401 if (ctx
->DrawBuffer
->Name
!= 0)
405 * GL_DITHER, GL_READ/DRAW_BUFFER, buffer binding state, etc. effect
406 * renderbuffer span/clear funcs.
408 if (new_state
& (_NEW_COLOR
| _NEW_BUFFERS
)) {
409 XMesaBuffer xmbuf
= XMESA_BUFFER(ctx
->DrawBuffer
);
410 struct xmesa_renderbuffer
*front_xrb
, *back_xrb
;
412 front_xrb
= xmbuf
->frontxrb
;
414 xmesa_set_renderbuffer_funcs(front_xrb
, xmesa
->pixelformat
,
415 xmesa
->xm_visual
->BitsPerPixel
);
416 front_xrb
->clearFunc
= clear_pixmap
;
419 back_xrb
= xmbuf
->backxrb
;
421 xmesa_set_renderbuffer_funcs(back_xrb
, xmesa
->pixelformat
,
422 xmesa
->xm_visual
->BitsPerPixel
);
423 if (xmbuf
->backxrb
->pixmap
) {
424 back_xrb
->clearFunc
= clear_pixmap
;
427 switch (xmesa
->xm_visual
->BitsPerPixel
) {
429 if (xmesa
->xm_visual
->hpcr_clear_flag
) {
430 back_xrb
->clearFunc
= clear_HPCR_ximage
;
433 back_xrb
->clearFunc
= clear_8bit_ximage
;
437 back_xrb
->clearFunc
= clear_16bit_ximage
;
440 back_xrb
->clearFunc
= clear_24bit_ximage
;
443 back_xrb
->clearFunc
= clear_32bit_ximage
;
446 back_xrb
->clearFunc
= clear_nbit_ximage
;
453 if (xmesa
->xm_visual
->hpcr_clear_flag
) {
454 /* this depends on whether we're drawing to the front or back buffer */
458 ctx
->Driver
.ClearColor
= clear_color_HPCR_pixmap
;
461 ctx
->Driver
.ClearColor
= clear_color_HPCR_ximage
;
464 (void) clear_color_HPCR_pixmap
;
465 (void) clear_color_HPCR_ximage
;
473 * Called by glViewport.
474 * This is a good time for us to poll the current X window size and adjust
475 * our renderbuffers to match the current window size.
476 * Remember, we have no opportunity to respond to conventional
477 * X Resize/StructureNotify events since the X driver has no event loop.
479 * Note that this trick isn't fool-proof. If the application never calls
480 * glViewport, our notion of the current window size may be incorrect.
481 * That problem led to the GLX_MESA_resize_buffers extension.
484 xmesa_viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
486 XMesaContext xmctx
= XMESA_CONTEXT(ctx
);
487 XMesaBuffer xmdrawbuf
= XMESA_BUFFER(ctx
->WinSysDrawBuffer
);
488 XMesaBuffer xmreadbuf
= XMESA_BUFFER(ctx
->WinSysReadBuffer
);
489 xmesa_check_and_update_buffer_size(xmctx
, xmdrawbuf
);
490 xmesa_check_and_update_buffer_size(xmctx
, xmreadbuf
);
499 * Initialize the device driver function table with the functions
500 * we implement in this driver.
503 xmesa_init_driver_functions( XMesaVisual xmvisual
,
504 struct dd_function_table
*driver
)
506 driver
->UpdateState
= xmesa_update_state
;
507 driver
->Flush
= finish_or_flush
;
508 driver
->Finish
= finish_or_flush
;
509 driver
->Viewport
= xmesa_viewport
;