Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / x11 / 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 "main/bufferobj.h"
33 #include "main/buffers.h"
34 #include "main/context.h"
35 #include "main/colormac.h"
36 #include "main/depth.h"
37 #include "main/drawpix.h"
38 #include "main/extensions.h"
39 #include "main/framebuffer.h"
40 #include "main/macros.h"
41 #include "main/image.h"
42 #include "main/imports.h"
43 #include "main/mtypes.h"
44 #include "main/pbo.h"
45 #include "main/state.h"
46 #include "main/texobj.h"
47 #include "main/teximage.h"
48 #include "main/texstore.h"
49 #include "main/texformat.h"
50 #include "swrast/swrast.h"
51 #include "swrast/s_context.h"
52 #include "swrast_setup/swrast_setup.h"
53 #include "tnl/tnl.h"
54 #include "tnl/t_context.h"
55 #include "drivers/common/meta.h"
56 #include "xmesaP.h"
57
58
59
60 /*
61  * Dithering kernels and lookup tables.
62  */
63
64 const int xmesa_kernel8[DITH_DY * DITH_DX] = {
65     0 * MAXC,  8 * MAXC,  2 * MAXC, 10 * MAXC,
66    12 * MAXC,  4 * MAXC, 14 * MAXC,  6 * MAXC,
67     3 * MAXC, 11 * MAXC,  1 * MAXC,  9 * MAXC,
68    15 * MAXC,  7 * MAXC, 13 * MAXC,  5 * MAXC,
69 };
70
71 const short xmesa_HPCR_DRGB[3][2][16] = {
72    {
73       { 16, -4,  1,-11, 14, -6,  3, -9, 15, -5,  2,-10, 13, -7,  4, -8},
74       {-15,  5,  0, 12,-13,  7, -2, 10,-14,  6, -1, 11,-12,  8, -3,  9}
75    },
76    {
77       {-11, 15, -7,  3, -8, 14, -4,  2,-10, 16, -6,  4, -9, 13, -5,  1},
78       { 12,-14,  8, -2,  9,-13,  5, -1, 11,-15,  7, -3, 10,-12,  6,  0}
79    },
80    {
81       {  6,-18, 26,-14,  2,-22, 30,-10,  8,-16, 28,-12,  4,-20, 32, -8},
82       { -4, 20,-24, 16,  0, 24,-28, 12, -6, 18,-26, 14, -2, 22,-30, 10}
83    }
84 };
85
86 const int xmesa_kernel1[16] = {
87    0*47,  9*47,  4*47, 12*47,     /* 47 = (255*3)/16 */
88    6*47,  2*47, 14*47,  8*47,
89   10*47,  1*47,  5*47, 11*47,
90    7*47, 13*47,  3*47, 15*47
91 };
92
93
94 static void
95 finish_or_flush( struct gl_context *ctx )
96 {
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 }
104
105
106 static void
107 clear_color( struct gl_context *ctx, const GLfloat color[4] )
108 {
109    if (ctx->DrawBuffer->Name == 0) {
110       const XMesaContext xmesa = XMESA_CONTEXT(ctx);
111       XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
112
113       CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
114       CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
115       CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
116       CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
117       xmesa->clearpixel = xmesa_color_to_pixel( ctx,
118                                                 xmesa->clearcolor[0],
119                                                 xmesa->clearcolor[1],
120                                                 xmesa->clearcolor[2],
121                                                 xmesa->clearcolor[3],
122                                                 xmesa->xm_visual->undithered_pf );
123       _glthread_LOCK_MUTEX(_xmesa_lock);
124       XMesaSetForeground( xmesa->display, xmbuf->cleargc,
125                           xmesa->clearpixel );
126       _glthread_UNLOCK_MUTEX(_xmesa_lock);
127    }
128 }
129
130
131
132 /* Implements glColorMask() */
133 static void
134 color_mask(struct gl_context *ctx,
135            GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
136 {
137    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
138    XMesaBuffer xmbuf;
139    const int xclass = xmesa->xm_visual->visualType;
140    (void) amask;
141
142    if (ctx->DrawBuffer->Name != 0)
143       return;
144
145    xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
146
147    if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
148       unsigned long m;
149       if (rmask && gmask && bmask) {
150          m = ((unsigned long)~0L);
151       }
152       else {
153          m = 0;
154          if (rmask)   m |= GET_REDMASK(xmesa->xm_visual);
155          if (gmask)   m |= GET_GREENMASK(xmesa->xm_visual);
156          if (bmask)   m |= GET_BLUEMASK(xmesa->xm_visual);
157       }
158       XMesaSetPlaneMask( xmesa->display, xmbuf->cleargc, m );
159    }
160 }
161
162
163
164 /**********************************************************************/
165 /*** glClear implementations                                        ***/
166 /**********************************************************************/
167
168
169 /**
170  * Clear the front or back color buffer, if it's implemented with a pixmap.
171  */
172 static void
173 clear_pixmap(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
174              GLint x, GLint y, GLint width, GLint height)
175 {
176    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
177    XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
178
179    assert(xmbuf);
180    assert(xrb->pixmap);
181    assert(xmesa);
182    assert(xmesa->display);
183    assert(xrb->pixmap);
184    assert(xmbuf->cleargc);
185
186    XMesaFillRectangle( xmesa->display, xrb->pixmap, xmbuf->cleargc,
187                        x, xrb->Base.Height - y - height,
188                        width, height );
189 }
190
191
192 static void
193 clear_8bit_ximage( struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
194                    GLint x, GLint y, GLint width, GLint height )
195 {
196    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
197    GLint i;
198    for (i = 0; i < height; i++) {
199       GLubyte *ptr = PIXEL_ADDR1(xrb, x, y + i);
200       memset( ptr, xmesa->clearpixel, width );
201    }
202 }
203
204
205 static void
206 clear_HPCR_ximage( struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
207                    GLint x, GLint y, GLint width, GLint height )
208 {
209    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
210    GLint i;
211    for (i = y; i < y + height; i++) {
212       GLubyte *ptr = PIXEL_ADDR1( xrb, x, i );
213       int j;
214       const GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
215       if (i & 1) {
216          sptr += 16;
217       }
218       for (j = x; j < x + width; j++) {
219          *ptr = sptr[j&15];
220          ptr++;
221       }
222    }
223 }
224
225
226 static void
227 clear_16bit_ximage( struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
228                     GLint x, GLint y, GLint width, GLint height)
229 {
230    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
231    GLuint pixel = (GLuint) xmesa->clearpixel;
232    GLint i, j;
233
234    if (xmesa->swapbytes) {
235       pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
236    }
237
238    for (j = 0; j < height; j++) {
239       GLushort *ptr2 = PIXEL_ADDR2(xrb, x, y + j);
240       for (i = 0; i < width; i++) {
241          ptr2[i] = pixel;
242       }
243    }
244 }
245
246
247 /* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
248 static void
249 clear_24bit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
250                    GLint x, GLint y, GLint width, GLint height)
251 {
252    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
253    const GLubyte r = xmesa->clearcolor[0];
254    const GLubyte g = xmesa->clearcolor[1];
255    const GLubyte b = xmesa->clearcolor[2];
256
257    if (r == g && g == b) {
258       /* same value for all three components (gray) */
259       GLint j;
260       for (j = 0; j < height; j++) {
261          bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y + j);
262          memset(ptr3, r, 3 * width);
263       }
264    }
265    else {
266       /* non-gray clear color */
267       GLint i, j;
268       for (j = 0; j < height; j++) {
269          bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y + j);
270          for (i = 0; i < width; i++) {
271             ptr3->r = r;
272             ptr3->g = g;
273             ptr3->b = b;
274             ptr3++;
275          }
276       }
277    }
278 }
279
280
281 static void
282 clear_32bit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
283                    GLint x, GLint y, GLint width, GLint height)
284 {
285    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
286    register GLuint pixel = (GLuint) xmesa->clearpixel;
287
288    if (!xrb->ximage)
289       return;
290
291    if (xmesa->swapbytes) {
292       pixel = ((pixel >> 24) & 0x000000ff)
293             | ((pixel >> 8)  & 0x0000ff00)
294             | ((pixel << 8)  & 0x00ff0000)
295             | ((pixel << 24) & 0xff000000);
296    }
297
298    if (width == xrb->Base.Width && height == xrb->Base.Height) {
299       /* clearing whole buffer */
300       const GLuint n = xrb->Base.Width * xrb->Base.Height;
301       GLuint *ptr4 = (GLuint *) xrb->ximage->data;
302       if (pixel == 0) {
303          /* common case */
304          memset(ptr4, pixel, 4 * n);
305       }
306       else {
307          GLuint i;
308          for (i = 0; i < n; i++)
309             ptr4[i] = pixel;
310       }
311    }
312    else {
313       /* clearing scissored region */
314       GLint i, j;
315       for (j = 0; j < height; j++) {
316          GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y + j);
317          for (i = 0; i < width; i++) {
318             ptr4[i] = pixel;
319          }
320       }
321    }
322 }
323
324
325 static void
326 clear_nbit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
327                   GLint x, GLint y, GLint width, GLint height)
328 {
329    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
330    XMesaImage *img = xrb->ximage;
331    GLint i, j;
332
333    /* TODO: optimize this */
334    y = YFLIP(xrb, y);
335    for (j = 0; j < height; j++) {
336       for (i = 0; i < width; i++) {
337          XMesaPutPixel(img, x+i, y-j, xmesa->clearpixel);
338       }
339    }
340 }
341
342
343
344 static void
345 clear_buffers(struct gl_context *ctx, GLbitfield buffers)
346 {
347    if (ctx->DrawBuffer->Name == 0) {
348       /* this is a window system framebuffer */
349       const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask[0];
350       XMesaBuffer b = XMESA_BUFFER(ctx->DrawBuffer);
351       const GLint x = ctx->DrawBuffer->_Xmin;
352       const GLint y = ctx->DrawBuffer->_Ymin;
353       const GLint width = ctx->DrawBuffer->_Xmax - x;
354       const GLint height = ctx->DrawBuffer->_Ymax - y;
355
356       /* we can't handle color or index masking */
357       if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
358          if (buffers & BUFFER_BIT_FRONT_LEFT) {
359             /* clear front color buffer */
360             struct gl_renderbuffer *frontRb
361                = ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
362             if (b->frontxrb == xmesa_renderbuffer(frontRb)) {
363                /* renderbuffer is not wrapped - great! */
364                b->frontxrb->clearFunc(ctx, b->frontxrb, x, y, width, height);
365                buffers &= ~BUFFER_BIT_FRONT_LEFT;
366             }
367             else {
368                /* we can't directly clear an alpha-wrapped color buffer */
369             }
370          }
371          if (buffers & BUFFER_BIT_BACK_LEFT) {
372             /* clear back color buffer */
373             struct gl_renderbuffer *backRb
374                = ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
375             if (b->backxrb == xmesa_renderbuffer(backRb)) {
376                /* renderbuffer is not wrapped - great! */
377                b->backxrb->clearFunc(ctx, b->backxrb, x, y, width, height);
378                buffers &= ~BUFFER_BIT_BACK_LEFT;
379             }
380          }
381       }
382    }
383    if (buffers)
384       _swrast_Clear(ctx, buffers);
385 }
386
387
388 /* XXX these functions haven't been tested in the Xserver environment */
389
390
391 /**
392  * Check if we can do an optimized glDrawPixels into an 8R8G8B visual.
393  */
394 static GLboolean
395 can_do_DrawPixels_8R8G8B(struct gl_context *ctx, GLenum format, GLenum type)
396 {
397    if (format == GL_BGRA &&
398        type == GL_UNSIGNED_BYTE &&
399        ctx->DrawBuffer &&
400        ctx->DrawBuffer->Name == 0 &&
401        ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
402        ctx->Pixel.ZoomY == 1.0 &&
403        ctx->_ImageTransferState == 0 /* no color tables, scale/bias, etc */) {
404       const SWcontext *swrast = SWRAST_CONTEXT(ctx);
405
406       if (swrast->NewState)
407          _swrast_validate_derived( ctx );
408       
409       if ((swrast->_RasterMask & ~CLIP_BIT) == 0) /* no blend, z-test, etc */ {
410          struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
411          if (rb) {
412             struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb->Wrapped);
413             if (xrb &&
414                 xrb->pixmap && /* drawing to pixmap or window */
415                 _mesa_get_format_bits(xrb->Base.Format, GL_ALPHA_BITS) == 0) {
416                return GL_TRUE;
417             }
418          }
419       }
420    }
421    return GL_FALSE;
422 }
423
424
425 /**
426  * This function implements glDrawPixels() with an XPutImage call when
427  * drawing to the front buffer (X Window drawable).
428  * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
429  */
430 static void
431 xmesa_DrawPixels_8R8G8B( struct gl_context *ctx,
432                          GLint x, GLint y, GLsizei width, GLsizei height,
433                          GLenum format, GLenum type,
434                          const struct gl_pixelstore_attrib *unpack,
435                          const GLvoid *pixels )
436 {
437    if (can_do_DrawPixels_8R8G8B(ctx, format, type)) {
438       const SWcontext *swrast = SWRAST_CONTEXT( ctx );
439       struct gl_pixelstore_attrib clippedUnpack = *unpack;
440       int dstX = x;
441       int dstY = y;
442       int w = width;
443       int h = height;
444
445       if (swrast->NewState)
446          _swrast_validate_derived( ctx );
447
448       if (_mesa_is_bufferobj(unpack->BufferObj)) {
449          /* unpack from PBO */
450          GLubyte *buf;
451          if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
452                                         format, type, INT_MAX, pixels)) {
453             _mesa_error(ctx, GL_INVALID_OPERATION,
454                         "glDrawPixels(invalid PBO access)");
455             return;
456          }
457          buf = (GLubyte *) ctx->Driver.MapBuffer(ctx,
458                                                  GL_PIXEL_UNPACK_BUFFER_EXT,
459                                                  GL_READ_ONLY_ARB,
460                                                  unpack->BufferObj);
461          if (!buf) {
462             /* buffer is already mapped - that's an error */
463             _mesa_error(ctx, GL_INVALID_OPERATION,
464                         "glDrawPixels(PBO is mapped)");
465             return;
466          }
467          pixels = ADD_POINTERS(buf, pixels);
468       }
469
470       if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
471          const XMesaContext xmesa = XMESA_CONTEXT(ctx);
472          XMesaDisplay *dpy = xmesa->xm_visual->display;
473          XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
474          const XMesaGC gc = xmbuf->cleargc;  /* effected by glColorMask */
475          struct xmesa_renderbuffer *xrb
476             = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
477          const int srcX = clippedUnpack.SkipPixels;
478          const int srcY = clippedUnpack.SkipRows;
479          const int rowLength = clippedUnpack.RowLength;
480          XMesaImage ximage;
481
482          ASSERT(xmesa->xm_visual->dithered_pf == PF_8R8G8B);
483          ASSERT(xmesa->xm_visual->undithered_pf == PF_8R8G8B);
484          ASSERT(dpy);
485          ASSERT(gc);
486
487          /* This is a little tricky since all coordinates up to now have
488           * been in the OpenGL bottom-to-top orientation.  X is top-to-bottom
489           * so we have to carefully compute the Y coordinates/addresses here.
490           */
491          memset(&ximage, 0, sizeof(XMesaImage));
492          ximage.width = width;
493          ximage.height = height;
494          ximage.format = ZPixmap;
495          ximage.data = (char *) pixels
496             + ((srcY + h - 1) * rowLength + srcX) * 4;
497          ximage.byte_order = LSBFirst;
498          ximage.bitmap_unit = 32;
499          ximage.bitmap_bit_order = LSBFirst;
500          ximage.bitmap_pad = 32;
501          ximage.depth = 32;
502          ximage.bits_per_pixel = 32;
503          ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */
504          /* it seems we don't need to set the ximage.red/green/blue_mask fields */
505          /* flip Y axis for dest position */
506          dstY = YFLIP(xrb, dstY) - h + 1;
507          XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
508       }
509
510       if (_mesa_is_bufferobj(unpack->BufferObj)) {
511          ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
512                                  unpack->BufferObj);
513       }
514    }
515    else {
516       /* software fallback */
517       _swrast_DrawPixels(ctx, x, y, width, height,
518                          format, type, unpack, pixels);
519    }
520 }
521
522
523
524 /**
525  * Check if we can do an optimized glDrawPixels into an 5R6G5B visual.
526  */
527 static GLboolean
528 can_do_DrawPixels_5R6G5B(struct gl_context *ctx, GLenum format, GLenum type)
529 {
530    if (format == GL_RGB &&
531        type == GL_UNSIGNED_SHORT_5_6_5 &&
532        !ctx->Color.DitherFlag &&  /* no dithering */
533        ctx->DrawBuffer &&
534        ctx->DrawBuffer->Name == 0 &&
535        ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
536        ctx->Pixel.ZoomY == 1.0 &&
537        ctx->_ImageTransferState == 0 /* no color tables, scale/bias, etc */) {
538       const SWcontext *swrast = SWRAST_CONTEXT(ctx);
539
540       if (swrast->NewState)
541          _swrast_validate_derived( ctx );
542       
543       if ((swrast->_RasterMask & ~CLIP_BIT) == 0) /* no blend, z-test, etc */ {
544          struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
545          if (rb) {
546             struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb->Wrapped);
547             if (xrb &&
548                 xrb->pixmap && /* drawing to pixmap or window */
549                 _mesa_get_format_bits(xrb->Base.Format, GL_ALPHA_BITS) == 0) {
550                return GL_TRUE;
551             }
552          }
553       }
554    }
555    return GL_FALSE;
556 }
557
558
559 /**
560  * This function implements glDrawPixels() with an XPutImage call when
561  * drawing to the front buffer (X Window drawable).  The image format
562  * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to
563  * match the PF_5R6G5B pixel format.
564  */
565 static void
566 xmesa_DrawPixels_5R6G5B( struct gl_context *ctx,
567                          GLint x, GLint y, GLsizei width, GLsizei height,
568                          GLenum format, GLenum type,
569                          const struct gl_pixelstore_attrib *unpack,
570                          const GLvoid *pixels )
571 {
572    if (can_do_DrawPixels_5R6G5B(ctx, format, type)) {
573       const SWcontext *swrast = SWRAST_CONTEXT( ctx );
574       struct gl_pixelstore_attrib clippedUnpack = *unpack;
575       int dstX = x;
576       int dstY = y;
577       int w = width;
578       int h = height;
579
580       if (swrast->NewState)
581          _swrast_validate_derived( ctx );
582       
583       if (_mesa_is_bufferobj(unpack->BufferObj)) {
584          /* unpack from PBO */
585          GLubyte *buf;
586          if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
587                                         format, type, INT_MAX, pixels)) {
588             _mesa_error(ctx, GL_INVALID_OPERATION,
589                         "glDrawPixels(invalid PBO access)");
590             return;
591          }
592          buf = (GLubyte *) ctx->Driver.MapBuffer(ctx,
593                                                  GL_PIXEL_UNPACK_BUFFER_EXT,
594                                                  GL_READ_ONLY_ARB,
595                                                  unpack->BufferObj);
596          if (!buf) {
597             /* buffer is already mapped - that's an error */
598             _mesa_error(ctx, GL_INVALID_OPERATION,
599                         "glDrawPixels(PBO is mapped)");
600             return;
601          }
602          pixels = ADD_POINTERS(buf, pixels);
603       }
604
605       if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
606          const XMesaContext xmesa = XMESA_CONTEXT(ctx);
607          XMesaDisplay *dpy = xmesa->xm_visual->display;
608          XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
609          const XMesaGC gc = xmbuf->cleargc;  /* effected by glColorMask */
610          struct xmesa_renderbuffer *xrb
611             = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
612          const int srcX = clippedUnpack.SkipPixels;
613          const int srcY = clippedUnpack.SkipRows;
614          const int rowLength = clippedUnpack.RowLength;
615          XMesaImage ximage;
616
617          ASSERT(xmesa->xm_visual->undithered_pf == PF_5R6G5B);
618          ASSERT(dpy);
619          ASSERT(gc);
620
621          /* This is a little tricky since all coordinates up to now have
622           * been in the OpenGL bottom-to-top orientation.  X is top-to-bottom
623           * so we have to carefully compute the Y coordinates/addresses here.
624           */
625          memset(&ximage, 0, sizeof(XMesaImage));
626          ximage.width = width;
627          ximage.height = height;
628          ximage.format = ZPixmap;
629          ximage.data = (char *) pixels
630             + ((srcY + h - 1) * rowLength + srcX) * 2;
631          ximage.byte_order = LSBFirst;
632          ximage.bitmap_unit = 16;
633          ximage.bitmap_bit_order = LSBFirst;
634          ximage.bitmap_pad = 16;
635          ximage.depth = 16;
636          ximage.bits_per_pixel = 16;
637          ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */
638          /* it seems we don't need to set the ximage.red/green/blue_mask fields */
639          /* flip Y axis for dest position */
640          dstY = YFLIP(xrb, dstY) - h + 1;
641          XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
642       }
643
644       if (unpack->BufferObj->Name) {
645          ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
646                                  unpack->BufferObj);
647       }
648    }
649    else {
650       /* software fallback */
651       _swrast_DrawPixels(ctx, x, y, width, height,
652                          format, type, unpack, pixels);
653    }
654 }
655
656
657 /**
658  * Determine if we can do an optimized glCopyPixels.
659  */
660 static GLboolean
661 can_do_CopyPixels(struct gl_context *ctx, GLenum type)
662 {
663    if (type == GL_COLOR &&
664        ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */
665        ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
666        ctx->Pixel.ZoomY == 1.0 &&
667        ctx->Color.DrawBuffer[0] == GL_FRONT &&  /* copy to front buf */
668        ctx->Pixel.ReadBuffer == GL_FRONT &&    /* copy from front buf */
669        ctx->ReadBuffer->_ColorReadBuffer &&
670        ctx->DrawBuffer->_ColorDrawBuffers[0]) {
671       const SWcontext *swrast = SWRAST_CONTEXT( ctx );
672
673       if (swrast->NewState)
674          _swrast_validate_derived( ctx );
675
676       if ((swrast->_RasterMask & ~CLIP_BIT) == 0x0 &&
677           ctx->ReadBuffer &&
678           ctx->ReadBuffer->_ColorReadBuffer &&
679           ctx->DrawBuffer &&
680           ctx->DrawBuffer->_ColorDrawBuffers[0]) {
681          struct xmesa_renderbuffer *srcXrb
682             = xmesa_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer->Wrapped);
683          struct xmesa_renderbuffer *dstXrb
684             = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
685          if (srcXrb->pixmap && dstXrb->pixmap) {
686             return GL_TRUE;
687          }
688       }
689    }
690    return GL_FALSE;
691 }
692
693
694 /**
695  * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
696  * for the color buffer.  Don't support zooming, pixel transfer, etc.
697  * We do support copying from one window to another, ala glXMakeCurrentRead.
698  */
699 static void
700 xmesa_CopyPixels( struct gl_context *ctx,
701                   GLint srcx, GLint srcy, GLsizei width, GLsizei height,
702                   GLint destx, GLint desty, GLenum type )
703 {
704    if (can_do_CopyPixels(ctx, type)) {
705       const XMesaContext xmesa = XMESA_CONTEXT(ctx);
706       XMesaDisplay *dpy = xmesa->xm_visual->display;
707       XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
708       const XMesaGC gc = xmbuf->cleargc;  /* effected by glColorMask */
709       struct xmesa_renderbuffer *srcXrb
710          = xmesa_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer->Wrapped);
711       struct xmesa_renderbuffer *dstXrb
712          = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
713
714       ASSERT(dpy);
715       ASSERT(gc);
716
717       /* Note: we don't do any special clipping work here.  We could,
718        * but X will do it for us.
719        */
720       srcy = YFLIP(srcXrb, srcy) - height + 1;
721       desty = YFLIP(dstXrb, desty) - height + 1;
722       XCopyArea(dpy, srcXrb->pixmap, dstXrb->pixmap, gc,
723                 srcx, srcy, width, height, destx, desty);
724    }
725    else {
726       _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
727    }
728 }
729
730
731
732
733 /*
734  * Every driver should implement a GetString function in order to
735  * return a meaningful GL_RENDERER string.
736  */
737 static const GLubyte *
738 get_string( struct gl_context *ctx, GLenum name )
739 {
740    (void) ctx;
741    switch (name) {
742       case GL_RENDERER:
743          return (const GLubyte *) "Mesa X11";
744       case GL_VENDOR:
745          return NULL;
746       default:
747          return NULL;
748    }
749 }
750
751
752 /*
753  * We implement the glEnable function only because we care about
754  * dither enable/disable.
755  */
756 static void
757 enable( struct gl_context *ctx, GLenum pname, GLboolean state )
758 {
759    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
760
761    switch (pname) {
762       case GL_DITHER:
763          if (state)
764             xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
765          else
766             xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
767          break;
768       default:
769          ;  /* silence compiler warning */
770    }
771 }
772
773
774 static void
775 clear_color_HPCR_ximage( struct gl_context *ctx, const GLfloat color[4] )
776 {
777    int i;
778    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
779
780    CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
781    CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
782    CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
783    CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
784
785    if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
786       /* black is black */
787       memset( xmesa->xm_visual->hpcr_clear_ximage_pattern, 0x0 ,
788               sizeof(xmesa->xm_visual->hpcr_clear_ximage_pattern));
789    }
790    else {
791       /* build clear pattern */
792       for (i=0; i<16; i++) {
793          xmesa->xm_visual->hpcr_clear_ximage_pattern[0][i] =
794             DITHER_HPCR(i, 0,
795                         xmesa->clearcolor[0],
796                         xmesa->clearcolor[1],
797                         xmesa->clearcolor[2]);
798          xmesa->xm_visual->hpcr_clear_ximage_pattern[1][i]    =
799             DITHER_HPCR(i, 1,
800                         xmesa->clearcolor[0],
801                         xmesa->clearcolor[1],
802                         xmesa->clearcolor[2]);
803       }
804    }
805 }
806
807
808 static void
809 clear_color_HPCR_pixmap( struct gl_context *ctx, const GLfloat color[4] )
810 {
811    int i;
812    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
813
814    CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
815    CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
816    CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
817    CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
818
819    if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
820       /* black is black */
821       for (i=0; i<16; i++) {
822          XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0, 0);
823          XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1, 0);
824       }
825    }
826    else {
827       for (i=0; i<16; i++) {
828          XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0,
829                        DITHER_HPCR(i, 0,
830                                    xmesa->clearcolor[0],
831                                    xmesa->clearcolor[1],
832                                    xmesa->clearcolor[2]));
833          XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1,
834                        DITHER_HPCR(i, 1,
835                                    xmesa->clearcolor[0],
836                                    xmesa->clearcolor[1],
837                                    xmesa->clearcolor[2]));
838       }
839    }
840    /* change tile pixmap content */
841    XMesaPutImage(xmesa->display,
842                  (XMesaDrawable)xmesa->xm_visual->hpcr_clear_pixmap,
843                  XMESA_BUFFER(ctx->DrawBuffer)->cleargc,
844                  xmesa->xm_visual->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
845 }
846
847
848 /**
849  * Called when the driver should update its state, based on the new_state
850  * flags.
851  */
852 void
853 xmesa_update_state( struct gl_context *ctx, GLbitfield new_state )
854 {
855    const XMesaContext xmesa = XMESA_CONTEXT(ctx);
856
857    /* Propagate statechange information to swrast and swrast_setup
858     * modules.  The X11 driver has no internal GL-dependent state.
859     */
860    _swrast_InvalidateState( ctx, new_state );
861    _tnl_InvalidateState( ctx, new_state );
862    _vbo_InvalidateState( ctx, new_state );
863    _swsetup_InvalidateState( ctx, new_state );
864
865    if (ctx->DrawBuffer->Name != 0)
866       return;
867
868    /*
869     * GL_DITHER, GL_READ/DRAW_BUFFER, buffer binding state, etc. effect
870     * renderbuffer span/clear funcs.
871     * Check _NEW_COLOR to detect dither enable/disable.
872     */
873    if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) {
874       XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
875       struct xmesa_renderbuffer *front_xrb, *back_xrb;
876
877       front_xrb = xmbuf->frontxrb;
878       if (front_xrb) {
879          xmesa_set_renderbuffer_funcs(front_xrb, xmesa->pixelformat,
880                                       xmesa->xm_visual->BitsPerPixel);
881          front_xrb->clearFunc = clear_pixmap;
882       }
883
884       back_xrb = xmbuf->backxrb;
885       if (back_xrb) {
886          xmesa_set_renderbuffer_funcs(back_xrb, xmesa->pixelformat,
887                                       xmesa->xm_visual->BitsPerPixel);
888          if (xmbuf->backxrb->pixmap) {
889             back_xrb->clearFunc = clear_pixmap;
890          }
891          else {
892             switch (xmesa->xm_visual->BitsPerPixel) {
893             case 8:
894                if (xmesa->xm_visual->hpcr_clear_flag) {
895                   back_xrb->clearFunc = clear_HPCR_ximage;
896                }
897                else {
898                   back_xrb->clearFunc = clear_8bit_ximage;
899                }
900                break;
901             case 16:
902                back_xrb->clearFunc = clear_16bit_ximage;
903                break;
904             case 24:
905                back_xrb->clearFunc = clear_24bit_ximage;
906                break;
907             case 32:
908                back_xrb->clearFunc = clear_32bit_ximage;
909                break;
910             default:
911                back_xrb->clearFunc = clear_nbit_ximage;
912                break;
913             }
914          }
915       }
916    }
917
918    if (xmesa->xm_visual->hpcr_clear_flag) {
919       /* this depends on whether we're drawing to the front or back buffer */
920       /* XXX FIX THIS! */
921 #if 0
922       if (pixmap) {
923          ctx->Driver.ClearColor = clear_color_HPCR_pixmap;
924       }
925       else {
926          ctx->Driver.ClearColor = clear_color_HPCR_ximage;
927       }
928 #else
929       (void) clear_color_HPCR_pixmap;
930       (void) clear_color_HPCR_ximage;
931 #endif
932    }
933 }
934
935
936
937 /**
938  * In SW, we don't really compress GL_COMPRESSED_RGB[A] textures!
939  */
940 static gl_format
941 choose_tex_format( struct gl_context *ctx, GLint internalFormat,
942                    GLenum format, GLenum type )
943 {
944    switch (internalFormat) {
945       case GL_COMPRESSED_RGB_ARB:
946          return MESA_FORMAT_RGB888;
947       case GL_COMPRESSED_RGBA_ARB:
948          return MESA_FORMAT_RGBA8888;
949       default:
950          return _mesa_choose_tex_format(ctx, internalFormat, format, type);
951    }
952 }
953
954
955 /**
956  * Called by glViewport.
957  * This is a good time for us to poll the current X window size and adjust
958  * our renderbuffers to match the current window size.
959  * Remember, we have no opportunity to respond to conventional
960  * X Resize/StructureNotify events since the X driver has no event loop.
961  * Thus, we poll.
962  * Note that this trick isn't fool-proof.  If the application never calls
963  * glViewport, our notion of the current window size may be incorrect.
964  * That problem led to the GLX_MESA_resize_buffers extension.
965  */
966 static void
967 xmesa_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
968 {
969    XMesaContext xmctx = XMESA_CONTEXT(ctx);
970    XMesaBuffer xmdrawbuf = XMESA_BUFFER(ctx->WinSysDrawBuffer);
971    XMesaBuffer xmreadbuf = XMESA_BUFFER(ctx->WinSysReadBuffer);
972    xmesa_check_and_update_buffer_size(xmctx, xmdrawbuf);
973    xmesa_check_and_update_buffer_size(xmctx, xmreadbuf);
974    (void) x;
975    (void) y;
976    (void) w;
977    (void) h;
978 }
979
980
981 #if ENABLE_EXT_timer_query
982
983 /*
984  * The GL_EXT_timer_query extension is not enabled for the XServer
985  * indirect renderer.  Not sure about how/if wrapping of gettimeofday()
986  * is done, etc.
987  */
988
989 struct xmesa_query_object
990 {
991    struct gl_query_object Base;
992    struct timeval StartTime;
993 };
994
995
996 static struct gl_query_object *
997 xmesa_new_query_object(struct gl_context *ctx, GLuint id)
998 {
999    struct xmesa_query_object *q = CALLOC_STRUCT(xmesa_query_object);
1000    if (q) {
1001       q->Base.Id = id;
1002       q->Base.Ready = GL_TRUE;
1003    }
1004    return &q->Base;
1005 }
1006
1007
1008 static void
1009 xmesa_begin_query(struct gl_context *ctx, struct gl_query_object *q)
1010 {
1011    if (q->Target == GL_TIME_ELAPSED_EXT) {
1012       struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
1013       (void) gettimeofday(&xq->StartTime, NULL);
1014    }
1015 }
1016
1017
1018 /**
1019  * Return the difference between the two given times in microseconds.
1020  */
1021 #ifdef __VMS
1022 #define suseconds_t unsigned int
1023 #endif
1024 static GLuint64EXT
1025 time_diff(const struct timeval *t0, const struct timeval *t1)
1026 {
1027    GLuint64EXT seconds0 = t0->tv_sec & 0xff;  /* 0 .. 255 seconds */
1028    GLuint64EXT seconds1 = t1->tv_sec & 0xff;  /* 0 .. 255 seconds */
1029    GLuint64EXT nanosec0 = (seconds0 * 1000000 + t0->tv_usec) * 1000;
1030    GLuint64EXT nanosec1 = (seconds1 * 1000000 + t1->tv_usec) * 1000;
1031    return nanosec1 - nanosec0;
1032 }
1033
1034
1035 static void
1036 xmesa_end_query(struct gl_context *ctx, struct gl_query_object *q)
1037 {
1038    if (q->Target == GL_TIME_ELAPSED_EXT) {
1039       struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
1040       struct timeval endTime;
1041       (void) gettimeofday(&endTime, NULL);
1042       /* result is in nanoseconds! */
1043       q->Result = time_diff(&xq->StartTime, &endTime);
1044    }
1045    q->Ready = GL_TRUE;
1046 }
1047
1048 #endif /* ENABLE_timer_query */
1049
1050
1051 /**
1052  * Initialize the device driver function table with the functions
1053  * we implement in this driver.
1054  */
1055 void
1056 xmesa_init_driver_functions( XMesaVisual xmvisual,
1057                              struct dd_function_table *driver )
1058 {
1059    driver->GetString = get_string;
1060    driver->UpdateState = xmesa_update_state;
1061    driver->GetBufferSize = NULL; /* OBSOLETE */
1062    driver->Flush = finish_or_flush;
1063    driver->Finish = finish_or_flush;
1064    driver->ClearColor = clear_color;
1065    driver->ColorMask = color_mask;
1066    driver->Enable = enable;
1067    driver->Viewport = xmesa_viewport;
1068    if (TEST_META_FUNCS) {
1069       driver->Clear = _mesa_meta_Clear;
1070       driver->CopyPixels = _mesa_meta_CopyPixels;
1071       driver->BlitFramebuffer = _mesa_meta_BlitFramebuffer;
1072       driver->DrawPixels = _mesa_meta_DrawPixels;
1073       driver->Bitmap = _mesa_meta_Bitmap;
1074    }
1075    else {
1076       driver->Clear = clear_buffers;
1077       driver->CopyPixels = xmesa_CopyPixels;
1078       if (xmvisual->undithered_pf == PF_8R8G8B &&
1079           xmvisual->dithered_pf == PF_8R8G8B &&
1080           xmvisual->BitsPerPixel == 32) {
1081          driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
1082       }
1083       else if (xmvisual->undithered_pf == PF_5R6G5B) {
1084          driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
1085       }
1086    }
1087
1088 #if ENABLE_EXT_texure_compression_s3tc
1089    driver->ChooseTextureFormat = choose_tex_format;
1090 #else
1091    (void) choose_tex_format;
1092 #endif
1093
1094 #if ENABLE_EXT_timer_query
1095    driver->NewQueryObject = xmesa_new_query_object;
1096    driver->BeginQuery = xmesa_begin_query;
1097    driver->EndQuery = xmesa_end_query;
1098 #endif
1099 }
1100
1101
1102 #define XMESA_NEW_POINT  (_NEW_POINT | \
1103                           _NEW_RENDERMODE | \
1104                           _SWRAST_NEW_RASTERMASK)
1105
1106 #define XMESA_NEW_LINE   (_NEW_LINE | \
1107                           _NEW_TEXTURE | \
1108                           _NEW_LIGHT | \
1109                           _NEW_DEPTH | \
1110                           _NEW_RENDERMODE | \
1111                           _SWRAST_NEW_RASTERMASK)
1112
1113 #define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
1114                             _NEW_TEXTURE | \
1115                             _NEW_LIGHT | \
1116                             _NEW_DEPTH | \
1117                             _NEW_RENDERMODE | \
1118                             _SWRAST_NEW_RASTERMASK)
1119
1120
1121 /**
1122  * Extend the software rasterizer with our line/point/triangle
1123  * functions.
1124  * Called during context creation only.
1125  */
1126 void xmesa_register_swrast_functions( struct gl_context *ctx )
1127 {
1128    SWcontext *swrast = SWRAST_CONTEXT( ctx );
1129
1130    swrast->choose_point = xmesa_choose_point;
1131    swrast->choose_line = xmesa_choose_line;
1132    swrast->choose_triangle = xmesa_choose_triangle;
1133
1134    /* XXX these lines have no net effect.  Remove??? */
1135    swrast->InvalidatePointMask |= XMESA_NEW_POINT;
1136    swrast->InvalidateLineMask |= XMESA_NEW_LINE;
1137    swrast->InvalidateTriangleMask |= XMESA_NEW_TRIANGLE;
1138 }