don't pass x,y,width,height to clear functions
[mesa.git] / src / mesa / pipe / xlib / xm_dd.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.2
4 *
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
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.
23 */
24
25
26 /**
27 * \file xm_dd.h
28 * General device driver functions for Xlib driver.
29 */
30
31 #include "glxheader.h"
32 #include "bufferobj.h"
33 #include "buffers.h"
34 #include "context.h"
35 #include "colormac.h"
36 #include "depth.h"
37 #include "drawpix.h"
38 #include "extensions.h"
39 #include "framebuffer.h"
40 #include "macros.h"
41 #include "image.h"
42 #include "imports.h"
43 #include "mtypes.h"
44 #include "state.h"
45 #include "texobj.h"
46 #include "teximage.h"
47 #include "texstore.h"
48 #include "texformat.h"
49 #include "xmesaP.h"
50
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"
55
56
57 /*
58 * Dithering kernels and lookup tables.
59 */
60
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,
66 };
67
68 const short xmesa_HPCR_DRGB[3][2][16] = {
69 {
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}
72 },
73 {
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}
76 },
77 {
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}
80 }
81 };
82
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
88 };
89
90
91 static void
92 finish_or_flush( GLcontext *ctx )
93 {
94 #ifdef XFree86Server
95 /* NOT_NEEDED */
96 #else
97 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
98 if (xmesa) {
99 _glthread_LOCK_MUTEX(_xmesa_lock);
100 XSync( xmesa->display, False );
101 _glthread_UNLOCK_MUTEX(_xmesa_lock);
102 }
103 #endif
104 abort();
105 }
106
107
108 /**********************************************************************/
109 /*** glClear implementations ***/
110 /**********************************************************************/
111
112
113 /**
114 * Clear the front or back color buffer, if it's implemented with a pixmap.
115 */
116 static void
117 clear_pixmap(GLcontext *ctx, struct xmesa_renderbuffer *xrb, GLuint value)
118 {
119 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
120 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
121
122 assert(xmbuf);
123 assert(xrb->pixmap);
124 assert(xmesa);
125 assert(xmesa->display);
126 assert(xrb->pixmap);
127 assert(xmbuf->cleargc);
128
129 XMesaSetForeground( xmesa->display, xmbuf->cleargc, value );
130
131 XMesaFillRectangle( xmesa->display, xrb->pixmap, xmbuf->cleargc,
132 0, 0, xrb->St.Base.Width, xrb->St.Base.Height);
133 }
134
135
136 static void
137 clear_8bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb, GLuint value)
138 {
139 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
140 GLint width = xrb->St.Base.Width;
141 GLint height = xrb->St.Base.Height;
142 GLint i;
143 for (i = 0; i < height; i++) {
144 GLubyte *ptr = PIXEL_ADDR1(xrb, 0, i);
145 MEMSET( ptr, xmesa->clearpixel, width );
146 }
147 }
148
149
150 static void
151 clear_HPCR_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb, GLuint value)
152
153 {
154 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
155 GLint width = xrb->St.Base.Width;
156 GLint height = xrb->St.Base.Height;
157 GLint i;
158 for (i = 0; i < height; i++) {
159 GLubyte *ptr = PIXEL_ADDR1( xrb, 0, i );
160 int j;
161 const GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
162 if (i & 1) {
163 sptr += 16;
164 }
165 for (j = 0; j < width; j++) {
166 *ptr = sptr[j&15];
167 ptr++;
168 }
169 }
170 }
171
172
173 static void
174 clear_16bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb, GLuint value)
175 {
176 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
177 GLint width = xrb->St.Base.Width;
178 GLint height = xrb->St.Base.Height;
179 GLint i, j;
180
181 if (xmesa->swapbytes) {
182 value = ((value >> 8) & 0x00ff) | ((value << 8) & 0xff00);
183 }
184
185 for (j = 0; j < height; j++) {
186 GLushort *ptr2 = PIXEL_ADDR2(xrb, 0, j);
187 for (i = 0; i < width; i++) {
188 ptr2[i] = value;
189 }
190 }
191 }
192
193
194 /* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
195 static void
196 clear_24bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
197 GLuint value)
198 {
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;
204
205 if (r == g && g == b) {
206 /* same value for all three components (gray) */
207 GLint j;
208 for (j = 0; j < height; j++) {
209 bgr_t *ptr3 = PIXEL_ADDR3(xrb, 0, j);
210 MEMSET(ptr3, r, 3 * width);
211 }
212 }
213 else {
214 /* non-gray clear color */
215 GLint i, j;
216 for (j = 0; j < height; j++) {
217 bgr_t *ptr3 = PIXEL_ADDR3(xrb, 0, j);
218 for (i = 0; i < width; i++) {
219 ptr3->r = r;
220 ptr3->g = g;
221 ptr3->b = b;
222 ptr3++;
223 }
224 }
225 }
226 }
227
228
229 static void
230 clear_32bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
231 GLuint value)
232 {
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;
238
239 if (!xrb->ximage)
240 return;
241
242 if (xmesa->swapbytes) {
243 value = ((value >> 24) & 0x000000ff)
244 | ((value >> 8) & 0x0000ff00)
245 | ((value << 8) & 0x00ff0000)
246 | ((value << 24) & 0xff000000);
247 }
248
249 if (value == 0) {
250 /* common case */
251 _mesa_memset(ptr4, value, 4 * n);
252 }
253 else {
254 GLuint i;
255 for (i = 0; i < n; i++)
256 ptr4[i] = value;
257 }
258 }
259
260
261 static void
262 clear_nbit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb, GLuint value)
263 {
264 XMesaImage *img = xrb->ximage;
265 GLint width = xrb->St.Base.Width;
266 GLint height = xrb->St.Base.Height;
267 GLint i, j;
268 for (j = 0; j < height; j++) {
269 for (i = 0; i < width; i++) {
270 XMesaPutPixel(img, i, j, value);
271 }
272 }
273 }
274
275
276
277 void
278 xmesa_clear_buffers(GLcontext *ctx, GLbitfield buffers, GLuint value)
279 {
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);
284
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;
295 }
296 else {
297 /* we can't directly clear an alpha-wrapped color buffer */
298 }
299 }
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;
308 }
309 }
310 }
311 }
312 }
313
314
315 static void
316 clear_color_HPCR_ximage( GLcontext *ctx, const GLfloat color[4] )
317 {
318 int i;
319 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
320
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]);
325
326 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
327 /* black is black */
328 MEMSET( xmesa->xm_visual->hpcr_clear_ximage_pattern, 0x0 ,
329 sizeof(xmesa->xm_visual->hpcr_clear_ximage_pattern));
330 }
331 else {
332 /* build clear pattern */
333 for (i=0; i<16; i++) {
334 xmesa->xm_visual->hpcr_clear_ximage_pattern[0][i] =
335 DITHER_HPCR(i, 0,
336 xmesa->clearcolor[0],
337 xmesa->clearcolor[1],
338 xmesa->clearcolor[2]);
339 xmesa->xm_visual->hpcr_clear_ximage_pattern[1][i] =
340 DITHER_HPCR(i, 1,
341 xmesa->clearcolor[0],
342 xmesa->clearcolor[1],
343 xmesa->clearcolor[2]);
344 }
345 }
346 }
347
348
349 static void
350 clear_color_HPCR_pixmap( GLcontext *ctx, const GLfloat color[4] )
351 {
352 int i;
353 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
354
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]);
359
360 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
361 /* black is black */
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);
365 }
366 }
367 else {
368 for (i=0; i<16; i++) {
369 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0,
370 DITHER_HPCR(i, 0,
371 xmesa->clearcolor[0],
372 xmesa->clearcolor[1],
373 xmesa->clearcolor[2]));
374 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1,
375 DITHER_HPCR(i, 1,
376 xmesa->clearcolor[0],
377 xmesa->clearcolor[1],
378 xmesa->clearcolor[2]));
379 }
380 }
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);
386 }
387
388
389 /**
390 * Called when the driver should update its state, based on the new_state
391 * flags.
392 */
393 void
394 xmesa_update_state( GLcontext *ctx, GLbitfield new_state )
395 {
396 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
397
398 st_invalidate_state( ctx, new_state );
399
400
401 if (ctx->DrawBuffer->Name != 0)
402 return;
403
404 /*
405 * GL_DITHER, GL_READ/DRAW_BUFFER, buffer binding state, etc. effect
406 * renderbuffer span/clear funcs.
407 */
408 if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) {
409 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
410 struct xmesa_renderbuffer *front_xrb, *back_xrb;
411
412 front_xrb = xmbuf->frontxrb;
413 if (front_xrb) {
414 xmesa_set_renderbuffer_funcs(front_xrb, xmesa->pixelformat,
415 xmesa->xm_visual->BitsPerPixel);
416 front_xrb->clearFunc = clear_pixmap;
417 }
418
419 back_xrb = xmbuf->backxrb;
420 if (back_xrb) {
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;
425 }
426 else {
427 switch (xmesa->xm_visual->BitsPerPixel) {
428 case 8:
429 if (xmesa->xm_visual->hpcr_clear_flag) {
430 back_xrb->clearFunc = clear_HPCR_ximage;
431 }
432 else {
433 back_xrb->clearFunc = clear_8bit_ximage;
434 }
435 break;
436 case 16:
437 back_xrb->clearFunc = clear_16bit_ximage;
438 break;
439 case 24:
440 back_xrb->clearFunc = clear_24bit_ximage;
441 break;
442 case 32:
443 back_xrb->clearFunc = clear_32bit_ximage;
444 break;
445 default:
446 back_xrb->clearFunc = clear_nbit_ximage;
447 break;
448 }
449 }
450 }
451 }
452
453 if (xmesa->xm_visual->hpcr_clear_flag) {
454 /* this depends on whether we're drawing to the front or back buffer */
455 /* XXX FIX THIS! */
456 #if 0
457 if (pixmap) {
458 ctx->Driver.ClearColor = clear_color_HPCR_pixmap;
459 }
460 else {
461 ctx->Driver.ClearColor = clear_color_HPCR_ximage;
462 }
463 #else
464 (void) clear_color_HPCR_pixmap;
465 (void) clear_color_HPCR_ximage;
466 #endif
467 }
468 }
469
470
471
472 /**
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.
478 * Thus, we poll.
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.
482 */
483 static void
484 xmesa_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
485 {
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);
491 (void) x;
492 (void) y;
493 (void) w;
494 (void) h;
495 }
496
497
498 /**
499 * Initialize the device driver function table with the functions
500 * we implement in this driver.
501 */
502 void
503 xmesa_init_driver_functions( XMesaVisual xmvisual,
504 struct dd_function_table *driver )
505 {
506 driver->UpdateState = xmesa_update_state;
507 driver->Flush = finish_or_flush;
508 driver->Finish = finish_or_flush;
509 driver->Viewport = xmesa_viewport;
510 }