1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg
26848b8605Smrg/**
27848b8605Smrg * \file xm_dd.h
28848b8605Smrg * General device driver functions for Xlib driver.
29848b8605Smrg */
30848b8605Smrg
31848b8605Smrg#include "glxheader.h"
32848b8605Smrg#include "main/bufferobj.h"
33848b8605Smrg#include "main/context.h"
34848b8605Smrg#include "main/colormac.h"
35848b8605Smrg#include "main/fbobject.h"
36b8e80941Smrg#include "main/framebuffer.h"
37848b8605Smrg#include "main/macros.h"
38848b8605Smrg#include "main/mipmap.h"
39848b8605Smrg#include "main/image.h"
40848b8605Smrg#include "main/imports.h"
41848b8605Smrg#include "main/mtypes.h"
42848b8605Smrg#include "main/pbo.h"
43848b8605Smrg#include "main/texformat.h"
44848b8605Smrg#include "swrast/swrast.h"
45848b8605Smrg#include "swrast/s_context.h"
46848b8605Smrg#include "swrast_setup/swrast_setup.h"
47848b8605Smrg#include "tnl/tnl.h"
48848b8605Smrg#include "tnl/t_context.h"
49848b8605Smrg#include "drivers/common/meta.h"
50848b8605Smrg#include "xmesaP.h"
51848b8605Smrg
52848b8605Smrg
53848b8605Smrgstatic void
54848b8605Smrgfinish_or_flush( struct gl_context *ctx )
55848b8605Smrg{
56848b8605Smrg   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
57848b8605Smrg   if (xmesa) {
58848b8605Smrg      mtx_lock(&_xmesa_lock);
59848b8605Smrg      XSync( xmesa->display, False );
60848b8605Smrg      mtx_unlock(&_xmesa_lock);
61848b8605Smrg   }
62848b8605Smrg}
63848b8605Smrg
64848b8605Smrg
65848b8605Smrg/* Implements glColorMask() */
66848b8605Smrgstatic void
67848b8605Smrgcolor_mask(struct gl_context *ctx,
68848b8605Smrg           GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
69848b8605Smrg{
70848b8605Smrg   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
71848b8605Smrg   XMesaBuffer xmbuf;
72848b8605Smrg   const int xclass = xmesa->xm_visual->visualType;
73848b8605Smrg   (void) amask;
74848b8605Smrg
75848b8605Smrg   if (_mesa_is_user_fbo(ctx->DrawBuffer))
76848b8605Smrg      return;
77848b8605Smrg
78848b8605Smrg   xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
79848b8605Smrg
80848b8605Smrg   if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
81848b8605Smrg      unsigned long m;
82848b8605Smrg      if (rmask && gmask && bmask) {
83848b8605Smrg         m = ((unsigned long)~0L);
84848b8605Smrg      }
85848b8605Smrg      else {
86848b8605Smrg         m = 0;
87848b8605Smrg         if (rmask)   m |= GET_REDMASK(xmesa->xm_visual);
88848b8605Smrg         if (gmask)   m |= GET_GREENMASK(xmesa->xm_visual);
89848b8605Smrg         if (bmask)   m |= GET_BLUEMASK(xmesa->xm_visual);
90848b8605Smrg      }
91848b8605Smrg      XMesaSetPlaneMask( xmesa->display, xmbuf->cleargc, m );
92848b8605Smrg   }
93848b8605Smrg}
94848b8605Smrg
95848b8605Smrg
96848b8605Smrg
97848b8605Smrg/**********************************************************************/
98848b8605Smrg/*** glClear implementations                                        ***/
99848b8605Smrg/**********************************************************************/
100848b8605Smrg
101848b8605Smrg
102848b8605Smrg/**
103848b8605Smrg * Clear the front or back color buffer, if it's implemented with a pixmap.
104848b8605Smrg */
105848b8605Smrgstatic void
106848b8605Smrgclear_pixmap(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
107848b8605Smrg             GLint x, GLint y, GLint width, GLint height)
108848b8605Smrg{
109848b8605Smrg   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
110848b8605Smrg   XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
111848b8605Smrg
112848b8605Smrg   assert(xmbuf);
113848b8605Smrg   assert(xrb->pixmap);
114848b8605Smrg   assert(xmesa);
115848b8605Smrg   assert(xmesa->display);
116848b8605Smrg   assert(xrb->pixmap);
117848b8605Smrg   assert(xmbuf->cleargc);
118848b8605Smrg
119848b8605Smrg   XMesaFillRectangle( xmesa->display, xrb->pixmap, xmbuf->cleargc,
120848b8605Smrg                       x, xrb->Base.Base.Height - y - height,
121848b8605Smrg                       width, height );
122848b8605Smrg}
123848b8605Smrg
124848b8605Smrg
125848b8605Smrgstatic void
126848b8605Smrgclear_16bit_ximage( struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
127848b8605Smrg                    GLint x, GLint y, GLint width, GLint height)
128848b8605Smrg{
129848b8605Smrg   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
130848b8605Smrg   GLuint pixel = (GLuint) xmesa->clearpixel;
131848b8605Smrg   GLint i, j;
132848b8605Smrg
133848b8605Smrg   if (xmesa->swapbytes) {
134848b8605Smrg      pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
135848b8605Smrg   }
136848b8605Smrg
137848b8605Smrg   for (j = 0; j < height; j++) {
138848b8605Smrg      GLushort *ptr2 = PIXEL_ADDR2(xrb, x, y + j);
139848b8605Smrg      for (i = 0; i < width; i++) {
140848b8605Smrg         ptr2[i] = pixel;
141848b8605Smrg      }
142848b8605Smrg   }
143848b8605Smrg}
144848b8605Smrg
145848b8605Smrg
146848b8605Smrg/* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
147848b8605Smrgstatic void
148848b8605Smrgclear_24bit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
149848b8605Smrg                   GLint x, GLint y, GLint width, GLint height)
150848b8605Smrg{
151848b8605Smrg   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
152848b8605Smrg   const GLubyte r = xmesa->clearcolor[0];
153848b8605Smrg   const GLubyte g = xmesa->clearcolor[1];
154848b8605Smrg   const GLubyte b = xmesa->clearcolor[2];
155848b8605Smrg
156848b8605Smrg   if (r == g && g == b) {
157848b8605Smrg      /* same value for all three components (gray) */
158848b8605Smrg      GLint j;
159848b8605Smrg      for (j = 0; j < height; j++) {
160848b8605Smrg         bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y + j);
161848b8605Smrg         memset(ptr3, r, 3 * width);
162848b8605Smrg      }
163848b8605Smrg   }
164848b8605Smrg   else {
165848b8605Smrg      /* non-gray clear color */
166848b8605Smrg      GLint i, j;
167848b8605Smrg      for (j = 0; j < height; j++) {
168848b8605Smrg         bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y + j);
169848b8605Smrg         for (i = 0; i < width; i++) {
170848b8605Smrg            ptr3->r = r;
171848b8605Smrg            ptr3->g = g;
172848b8605Smrg            ptr3->b = b;
173848b8605Smrg            ptr3++;
174848b8605Smrg         }
175848b8605Smrg      }
176848b8605Smrg   }
177848b8605Smrg}
178848b8605Smrg
179848b8605Smrg
180848b8605Smrgstatic void
181848b8605Smrgclear_32bit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
182848b8605Smrg                   GLint x, GLint y, GLint width, GLint height)
183848b8605Smrg{
184848b8605Smrg   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
185848b8605Smrg   register GLuint pixel = (GLuint) xmesa->clearpixel;
186848b8605Smrg
187848b8605Smrg   if (!xrb->ximage)
188848b8605Smrg      return;
189848b8605Smrg
190848b8605Smrg   if (xmesa->swapbytes) {
191848b8605Smrg      pixel = ((pixel >> 24) & 0x000000ff)
192848b8605Smrg            | ((pixel >> 8)  & 0x0000ff00)
193848b8605Smrg            | ((pixel << 8)  & 0x00ff0000)
194848b8605Smrg            | ((pixel << 24) & 0xff000000);
195848b8605Smrg   }
196848b8605Smrg
197848b8605Smrg   if (width == xrb->Base.Base.Width && height == xrb->Base.Base.Height) {
198848b8605Smrg      /* clearing whole buffer */
199848b8605Smrg      const GLuint n = xrb->Base.Base.Width * xrb->Base.Base.Height;
200848b8605Smrg      GLuint *ptr4 = (GLuint *) xrb->ximage->data;
201848b8605Smrg      if (pixel == 0) {
202848b8605Smrg         /* common case */
203848b8605Smrg         memset(ptr4, pixel, 4 * n);
204848b8605Smrg      }
205848b8605Smrg      else {
206848b8605Smrg         GLuint i;
207848b8605Smrg         for (i = 0; i < n; i++)
208848b8605Smrg            ptr4[i] = pixel;
209848b8605Smrg      }
210848b8605Smrg   }
211848b8605Smrg   else {
212848b8605Smrg      /* clearing scissored region */
213848b8605Smrg      GLint i, j;
214848b8605Smrg      for (j = 0; j < height; j++) {
215848b8605Smrg         GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y + j);
216848b8605Smrg         for (i = 0; i < width; i++) {
217848b8605Smrg            ptr4[i] = pixel;
218848b8605Smrg         }
219848b8605Smrg      }
220848b8605Smrg   }
221848b8605Smrg}
222848b8605Smrg
223848b8605Smrg
224848b8605Smrgstatic void
225848b8605Smrgclear_nbit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
226848b8605Smrg                  GLint x, GLint y, GLint width, GLint height)
227848b8605Smrg{
228848b8605Smrg   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
229848b8605Smrg   XMesaImage *img = xrb->ximage;
230848b8605Smrg   GLint i, j;
231848b8605Smrg
232848b8605Smrg   /* TODO: optimize this */
233848b8605Smrg   y = YFLIP(xrb, y);
234848b8605Smrg   for (j = 0; j < height; j++) {
235848b8605Smrg      for (i = 0; i < width; i++) {
236848b8605Smrg         XMesaPutPixel(img, x+i, y-j, xmesa->clearpixel);
237848b8605Smrg      }
238848b8605Smrg   }
239848b8605Smrg}
240848b8605Smrg
241848b8605Smrg
242848b8605Smrg
243848b8605Smrgstatic void
244848b8605Smrgclear_buffers(struct gl_context *ctx, GLbitfield buffers)
245848b8605Smrg{
246848b8605Smrg   if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
247848b8605Smrg      /* this is a window system framebuffer */
248848b8605Smrg      const XMesaContext xmesa = XMESA_CONTEXT(ctx);
249848b8605Smrg      XMesaBuffer b = XMESA_BUFFER(ctx->DrawBuffer);
250848b8605Smrg      const GLint x = ctx->DrawBuffer->_Xmin;
251848b8605Smrg      const GLint y = ctx->DrawBuffer->_Ymin;
252848b8605Smrg      const GLint width = ctx->DrawBuffer->_Xmax - x;
253848b8605Smrg      const GLint height = ctx->DrawBuffer->_Ymax - y;
254848b8605Smrg
255848b8605Smrg      _mesa_unclamped_float_rgba_to_ubyte(xmesa->clearcolor,
256848b8605Smrg                                          ctx->Color.ClearColor.f);
257848b8605Smrg      xmesa->clearpixel = xmesa_color_to_pixel(ctx,
258848b8605Smrg                                               xmesa->clearcolor[0],
259848b8605Smrg                                               xmesa->clearcolor[1],
260848b8605Smrg                                               xmesa->clearcolor[2],
261848b8605Smrg                                               xmesa->clearcolor[3],
262848b8605Smrg                                               xmesa->xm_visual->undithered_pf);
263848b8605Smrg      XMesaSetForeground(xmesa->display, b->cleargc, xmesa->clearpixel);
264848b8605Smrg
265848b8605Smrg      /* we can't handle color or index masking */
266b8e80941Smrg      if (GET_COLORMASK(ctx->Color.ColorMask, 0) == 0xf &&
267b8e80941Smrg          ctx->Color.IndexMask == 0xffffffff) {
268848b8605Smrg         if (buffers & BUFFER_BIT_FRONT_LEFT) {
269848b8605Smrg            /* clear front color buffer */
270848b8605Smrg            struct gl_renderbuffer *frontRb
271848b8605Smrg               = ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
272848b8605Smrg            if (b->frontxrb == xmesa_renderbuffer(frontRb)) {
273848b8605Smrg               /* renderbuffer is not wrapped - great! */
274848b8605Smrg               b->frontxrb->clearFunc(ctx, b->frontxrb, x, y, width, height);
275848b8605Smrg               buffers &= ~BUFFER_BIT_FRONT_LEFT;
276848b8605Smrg            }
277848b8605Smrg            else {
278848b8605Smrg               /* we can't directly clear an alpha-wrapped color buffer */
279848b8605Smrg            }
280848b8605Smrg         }
281848b8605Smrg         if (buffers & BUFFER_BIT_BACK_LEFT) {
282848b8605Smrg            /* clear back color buffer */
283848b8605Smrg            struct gl_renderbuffer *backRb
284848b8605Smrg               = ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
285848b8605Smrg            if (b->backxrb == xmesa_renderbuffer(backRb)) {
286848b8605Smrg               /* renderbuffer is not wrapped - great! */
287848b8605Smrg               b->backxrb->clearFunc(ctx, b->backxrb, x, y, width, height);
288848b8605Smrg               buffers &= ~BUFFER_BIT_BACK_LEFT;
289848b8605Smrg            }
290848b8605Smrg         }
291848b8605Smrg      }
292848b8605Smrg   }
293848b8605Smrg   if (buffers)
294848b8605Smrg      _swrast_Clear(ctx, buffers);
295848b8605Smrg}
296848b8605Smrg
297848b8605Smrg
298848b8605Smrg/* XXX these functions haven't been tested in the Xserver environment */
299848b8605Smrg
300848b8605Smrg
301848b8605Smrg/**
302848b8605Smrg * Check if we can do an optimized glDrawPixels into an 8R8G8B visual.
303848b8605Smrg */
304848b8605Smrgstatic GLboolean
305848b8605Smrgcan_do_DrawPixels_8R8G8B(struct gl_context *ctx, GLenum format, GLenum type)
306848b8605Smrg{
307848b8605Smrg   if (format == GL_BGRA &&
308848b8605Smrg       type == GL_UNSIGNED_BYTE &&
309848b8605Smrg       ctx->DrawBuffer &&
310848b8605Smrg       _mesa_is_winsys_fbo(ctx->DrawBuffer) &&
311848b8605Smrg       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
312848b8605Smrg       ctx->Pixel.ZoomY == 1.0 &&
313848b8605Smrg       ctx->_ImageTransferState == 0 /* no color tables, scale/bias, etc */) {
314848b8605Smrg      const SWcontext *swrast = SWRAST_CONTEXT(ctx);
315848b8605Smrg
316848b8605Smrg      if (swrast->NewState)
317848b8605Smrg         _swrast_validate_derived( ctx );
318848b8605Smrg
319848b8605Smrg      if ((swrast->_RasterMask & ~CLIP_BIT) == 0) /* no blend, z-test, etc */ {
320848b8605Smrg         struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
321848b8605Smrg         if (rb) {
322848b8605Smrg            struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
323848b8605Smrg            if (xrb &&
324848b8605Smrg                xrb->pixmap && /* drawing to pixmap or window */
325848b8605Smrg                _mesa_get_format_bits(xrb->Base.Base.Format, GL_ALPHA_BITS) == 0) {
326848b8605Smrg               return GL_TRUE;
327848b8605Smrg            }
328848b8605Smrg         }
329848b8605Smrg      }
330848b8605Smrg   }
331848b8605Smrg   return GL_FALSE;
332848b8605Smrg}
333848b8605Smrg
334848b8605Smrg
335848b8605Smrg/**
336848b8605Smrg * This function implements glDrawPixels() with an XPutImage call when
337848b8605Smrg * drawing to the front buffer (X Window drawable).
338848b8605Smrg * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
339848b8605Smrg */
340848b8605Smrgstatic void
341848b8605Smrgxmesa_DrawPixels_8R8G8B( struct gl_context *ctx,
342848b8605Smrg                         GLint x, GLint y, GLsizei width, GLsizei height,
343848b8605Smrg                         GLenum format, GLenum type,
344848b8605Smrg                         const struct gl_pixelstore_attrib *unpack,
345848b8605Smrg                         const GLvoid *pixels )
346848b8605Smrg{
347848b8605Smrg   if (can_do_DrawPixels_8R8G8B(ctx, format, type)) {
348848b8605Smrg      const SWcontext *swrast = SWRAST_CONTEXT( ctx );
349848b8605Smrg      struct gl_pixelstore_attrib clippedUnpack = *unpack;
350848b8605Smrg      int dstX = x;
351848b8605Smrg      int dstY = y;
352848b8605Smrg      int w = width;
353848b8605Smrg      int h = height;
354848b8605Smrg
355848b8605Smrg      if (swrast->NewState)
356848b8605Smrg         _swrast_validate_derived( ctx );
357848b8605Smrg
358848b8605Smrg      if (_mesa_is_bufferobj(unpack->BufferObj)) {
359848b8605Smrg         /* unpack from PBO */
360848b8605Smrg         GLubyte *buf;
361848b8605Smrg         if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
362848b8605Smrg                                        format, type, INT_MAX, pixels)) {
363848b8605Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
364848b8605Smrg                        "glDrawPixels(invalid PBO access)");
365848b8605Smrg            return;
366848b8605Smrg         }
367848b8605Smrg         buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0,
368848b8605Smrg						      unpack->BufferObj->Size,
369848b8605Smrg						      GL_MAP_READ_BIT,
370848b8605Smrg						      unpack->BufferObj,
371848b8605Smrg                                                      MAP_INTERNAL);
372848b8605Smrg         if (!buf) {
373848b8605Smrg            return; /* error */
374848b8605Smrg         }
375848b8605Smrg         pixels = ADD_POINTERS(buf, pixels);
376848b8605Smrg      }
377848b8605Smrg
378848b8605Smrg      if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
379848b8605Smrg         const XMesaContext xmesa = XMESA_CONTEXT(ctx);
380848b8605Smrg         XMesaDisplay *dpy = xmesa->xm_visual->display;
381848b8605Smrg         XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
382848b8605Smrg         const XMesaGC gc = xmbuf->cleargc;  /* effected by glColorMask */
383848b8605Smrg         struct xmesa_renderbuffer *xrb
384848b8605Smrg            = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
385848b8605Smrg         const int srcX = clippedUnpack.SkipPixels;
386848b8605Smrg         const int srcY = clippedUnpack.SkipRows;
387848b8605Smrg         const int rowLength = clippedUnpack.RowLength;
388848b8605Smrg         XMesaImage ximage;
389848b8605Smrg
390b8e80941Smrg         assert(xmesa->xm_visual->dithered_pf == PF_8R8G8B);
391b8e80941Smrg         assert(xmesa->xm_visual->undithered_pf == PF_8R8G8B);
392b8e80941Smrg         assert(dpy);
393b8e80941Smrg         assert(gc);
394848b8605Smrg
395848b8605Smrg         /* This is a little tricky since all coordinates up to now have
396848b8605Smrg          * been in the OpenGL bottom-to-top orientation.  X is top-to-bottom
397848b8605Smrg          * so we have to carefully compute the Y coordinates/addresses here.
398848b8605Smrg          */
399848b8605Smrg         memset(&ximage, 0, sizeof(XMesaImage));
400848b8605Smrg         ximage.width = width;
401848b8605Smrg         ximage.height = height;
402848b8605Smrg         ximage.format = ZPixmap;
403848b8605Smrg         ximage.data = (char *) pixels
404848b8605Smrg            + ((srcY + h - 1) * rowLength + srcX) * 4;
405848b8605Smrg         ximage.byte_order = LSBFirst;
406848b8605Smrg         ximage.bitmap_unit = 32;
407848b8605Smrg         ximage.bitmap_bit_order = LSBFirst;
408848b8605Smrg         ximage.bitmap_pad = 32;
409848b8605Smrg         ximage.depth = 32;
410848b8605Smrg         ximage.bits_per_pixel = 32;
411848b8605Smrg         ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */
412848b8605Smrg         /* it seems we don't need to set the ximage.red/green/blue_mask fields */
413848b8605Smrg         /* flip Y axis for dest position */
414848b8605Smrg         dstY = YFLIP(xrb, dstY) - h + 1;
415848b8605Smrg         XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
416848b8605Smrg      }
417848b8605Smrg
418848b8605Smrg      if (_mesa_is_bufferobj(unpack->BufferObj)) {
419848b8605Smrg         ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL);
420848b8605Smrg      }
421848b8605Smrg   }
422848b8605Smrg   else {
423848b8605Smrg      /* software fallback */
424848b8605Smrg      _swrast_DrawPixels(ctx, x, y, width, height,
425848b8605Smrg                         format, type, unpack, pixels);
426848b8605Smrg   }
427848b8605Smrg}
428848b8605Smrg
429848b8605Smrg
430848b8605Smrg
431848b8605Smrg/**
432848b8605Smrg * Check if we can do an optimized glDrawPixels into an 5R6G5B visual.
433848b8605Smrg */
434848b8605Smrgstatic GLboolean
435848b8605Smrgcan_do_DrawPixels_5R6G5B(struct gl_context *ctx, GLenum format, GLenum type)
436848b8605Smrg{
437848b8605Smrg   if (format == GL_RGB &&
438848b8605Smrg       type == GL_UNSIGNED_SHORT_5_6_5 &&
439848b8605Smrg       !ctx->Color.DitherFlag &&  /* no dithering */
440848b8605Smrg       ctx->DrawBuffer &&
441848b8605Smrg       _mesa_is_winsys_fbo(ctx->DrawBuffer) &&
442848b8605Smrg       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
443848b8605Smrg       ctx->Pixel.ZoomY == 1.0 &&
444848b8605Smrg       ctx->_ImageTransferState == 0 /* no color tables, scale/bias, etc */) {
445848b8605Smrg      const SWcontext *swrast = SWRAST_CONTEXT(ctx);
446848b8605Smrg
447848b8605Smrg      if (swrast->NewState)
448848b8605Smrg         _swrast_validate_derived( ctx );
449848b8605Smrg
450848b8605Smrg      if ((swrast->_RasterMask & ~CLIP_BIT) == 0) /* no blend, z-test, etc */ {
451848b8605Smrg         struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
452848b8605Smrg         if (rb) {
453848b8605Smrg            struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
454848b8605Smrg            if (xrb &&
455848b8605Smrg                xrb->pixmap && /* drawing to pixmap or window */
456848b8605Smrg                _mesa_get_format_bits(xrb->Base.Base.Format, GL_ALPHA_BITS) == 0) {
457848b8605Smrg               return GL_TRUE;
458848b8605Smrg            }
459848b8605Smrg         }
460848b8605Smrg      }
461848b8605Smrg   }
462848b8605Smrg   return GL_FALSE;
463848b8605Smrg}
464848b8605Smrg
465848b8605Smrg
466848b8605Smrg/**
467848b8605Smrg * This function implements glDrawPixels() with an XPutImage call when
468848b8605Smrg * drawing to the front buffer (X Window drawable).  The image format
469848b8605Smrg * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to
470848b8605Smrg * match the PF_5R6G5B pixel format.
471848b8605Smrg */
472848b8605Smrgstatic void
473848b8605Smrgxmesa_DrawPixels_5R6G5B( struct gl_context *ctx,
474848b8605Smrg                         GLint x, GLint y, GLsizei width, GLsizei height,
475848b8605Smrg                         GLenum format, GLenum type,
476848b8605Smrg                         const struct gl_pixelstore_attrib *unpack,
477848b8605Smrg                         const GLvoid *pixels )
478848b8605Smrg{
479848b8605Smrg   if (can_do_DrawPixels_5R6G5B(ctx, format, type)) {
480848b8605Smrg      const SWcontext *swrast = SWRAST_CONTEXT( ctx );
481848b8605Smrg      struct gl_pixelstore_attrib clippedUnpack = *unpack;
482848b8605Smrg      int dstX = x;
483848b8605Smrg      int dstY = y;
484848b8605Smrg      int w = width;
485848b8605Smrg      int h = height;
486848b8605Smrg
487848b8605Smrg      if (swrast->NewState)
488848b8605Smrg         _swrast_validate_derived( ctx );
489848b8605Smrg
490848b8605Smrg      if (_mesa_is_bufferobj(unpack->BufferObj)) {
491848b8605Smrg         /* unpack from PBO */
492848b8605Smrg         GLubyte *buf;
493848b8605Smrg         if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
494848b8605Smrg                                        format, type, INT_MAX, pixels)) {
495848b8605Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
496848b8605Smrg                        "glDrawPixels(invalid PBO access)");
497848b8605Smrg            return;
498848b8605Smrg         }
499848b8605Smrg         buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0,
500848b8605Smrg						      unpack->BufferObj->Size,
501848b8605Smrg						      GL_MAP_READ_BIT,
502848b8605Smrg						      unpack->BufferObj,
503848b8605Smrg                                                      MAP_INTERNAL);
504848b8605Smrg         if (!buf) {
505848b8605Smrg            return; /* error */
506848b8605Smrg         }
507848b8605Smrg         pixels = ADD_POINTERS(buf, pixels);
508848b8605Smrg      }
509848b8605Smrg
510848b8605Smrg      if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
511848b8605Smrg         const XMesaContext xmesa = XMESA_CONTEXT(ctx);
512848b8605Smrg         XMesaDisplay *dpy = xmesa->xm_visual->display;
513848b8605Smrg         XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
514848b8605Smrg         const XMesaGC gc = xmbuf->cleargc;  /* effected by glColorMask */
515848b8605Smrg         struct xmesa_renderbuffer *xrb
516848b8605Smrg            = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
517848b8605Smrg         const int srcX = clippedUnpack.SkipPixels;
518848b8605Smrg         const int srcY = clippedUnpack.SkipRows;
519848b8605Smrg         const int rowLength = clippedUnpack.RowLength;
520848b8605Smrg         XMesaImage ximage;
521848b8605Smrg
522b8e80941Smrg         assert(xmesa->xm_visual->undithered_pf == PF_5R6G5B);
523b8e80941Smrg         assert(dpy);
524b8e80941Smrg         assert(gc);
525848b8605Smrg
526848b8605Smrg         /* This is a little tricky since all coordinates up to now have
527848b8605Smrg          * been in the OpenGL bottom-to-top orientation.  X is top-to-bottom
528848b8605Smrg          * so we have to carefully compute the Y coordinates/addresses here.
529848b8605Smrg          */
530848b8605Smrg         memset(&ximage, 0, sizeof(XMesaImage));
531848b8605Smrg         ximage.width = width;
532848b8605Smrg         ximage.height = height;
533848b8605Smrg         ximage.format = ZPixmap;
534848b8605Smrg         ximage.data = (char *) pixels
535848b8605Smrg            + ((srcY + h - 1) * rowLength + srcX) * 2;
536848b8605Smrg         ximage.byte_order = LSBFirst;
537848b8605Smrg         ximage.bitmap_unit = 16;
538848b8605Smrg         ximage.bitmap_bit_order = LSBFirst;
539848b8605Smrg         ximage.bitmap_pad = 16;
540848b8605Smrg         ximage.depth = 16;
541848b8605Smrg         ximage.bits_per_pixel = 16;
542848b8605Smrg         ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */
543848b8605Smrg         /* it seems we don't need to set the ximage.red/green/blue_mask fields */
544848b8605Smrg         /* flip Y axis for dest position */
545848b8605Smrg         dstY = YFLIP(xrb, dstY) - h + 1;
546848b8605Smrg         XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
547848b8605Smrg      }
548848b8605Smrg
549848b8605Smrg      if (unpack->BufferObj->Name) {
550848b8605Smrg         ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL);
551848b8605Smrg      }
552848b8605Smrg   }
553848b8605Smrg   else {
554848b8605Smrg      /* software fallback */
555848b8605Smrg      _swrast_DrawPixels(ctx, x, y, width, height,
556848b8605Smrg                         format, type, unpack, pixels);
557848b8605Smrg   }
558848b8605Smrg}
559848b8605Smrg
560848b8605Smrg
561848b8605Smrg/**
562848b8605Smrg * Determine if we can do an optimized glCopyPixels.
563848b8605Smrg */
564848b8605Smrgstatic GLboolean
565848b8605Smrgcan_do_CopyPixels(struct gl_context *ctx, GLenum type)
566848b8605Smrg{
567848b8605Smrg   if (type == GL_COLOR &&
568848b8605Smrg       ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */
569848b8605Smrg       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
570848b8605Smrg       ctx->Pixel.ZoomY == 1.0 &&
571848b8605Smrg       ctx->Color.DrawBuffer[0] == GL_FRONT &&  /* copy to front buf */
572848b8605Smrg       ctx->Pixel.ReadBuffer == GL_FRONT &&    /* copy from front buf */
573848b8605Smrg       ctx->ReadBuffer->_ColorReadBuffer &&
574848b8605Smrg       ctx->DrawBuffer->_ColorDrawBuffers[0]) {
575848b8605Smrg      const SWcontext *swrast = SWRAST_CONTEXT( ctx );
576848b8605Smrg
577848b8605Smrg      if (swrast->NewState)
578848b8605Smrg         _swrast_validate_derived( ctx );
579848b8605Smrg
580848b8605Smrg      if ((swrast->_RasterMask & ~CLIP_BIT) == 0x0 &&
581848b8605Smrg          ctx->ReadBuffer &&
582848b8605Smrg          ctx->ReadBuffer->_ColorReadBuffer &&
583848b8605Smrg          ctx->DrawBuffer &&
584848b8605Smrg          ctx->DrawBuffer->_ColorDrawBuffers[0]) {
585848b8605Smrg         struct xmesa_renderbuffer *srcXrb
586848b8605Smrg            = xmesa_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
587848b8605Smrg         struct xmesa_renderbuffer *dstXrb
588848b8605Smrg            = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
589848b8605Smrg         if (srcXrb->pixmap && dstXrb->pixmap) {
590848b8605Smrg            return GL_TRUE;
591848b8605Smrg         }
592848b8605Smrg      }
593848b8605Smrg   }
594848b8605Smrg   return GL_FALSE;
595848b8605Smrg}
596848b8605Smrg
597848b8605Smrg
598848b8605Smrg/**
599848b8605Smrg * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
600848b8605Smrg * for the color buffer.  Don't support zooming, pixel transfer, etc.
601848b8605Smrg * We do support copying from one window to another, ala glXMakeCurrentRead.
602848b8605Smrg */
603848b8605Smrgstatic void
604848b8605Smrgxmesa_CopyPixels( struct gl_context *ctx,
605848b8605Smrg                  GLint srcx, GLint srcy, GLsizei width, GLsizei height,
606848b8605Smrg                  GLint destx, GLint desty, GLenum type )
607848b8605Smrg{
608848b8605Smrg   if (can_do_CopyPixels(ctx, type)) {
609848b8605Smrg      const XMesaContext xmesa = XMESA_CONTEXT(ctx);
610848b8605Smrg      XMesaDisplay *dpy = xmesa->xm_visual->display;
611848b8605Smrg      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
612848b8605Smrg      const XMesaGC gc = xmbuf->cleargc;  /* effected by glColorMask */
613848b8605Smrg      struct xmesa_renderbuffer *srcXrb
614848b8605Smrg         = xmesa_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
615848b8605Smrg      struct xmesa_renderbuffer *dstXrb
616848b8605Smrg         = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
617848b8605Smrg
618b8e80941Smrg      assert(dpy);
619b8e80941Smrg      assert(gc);
620848b8605Smrg
621848b8605Smrg      /* Note: we don't do any special clipping work here.  We could,
622848b8605Smrg       * but X will do it for us.
623848b8605Smrg       */
624848b8605Smrg      srcy = YFLIP(srcXrb, srcy) - height + 1;
625848b8605Smrg      desty = YFLIP(dstXrb, desty) - height + 1;
626848b8605Smrg      XCopyArea(dpy, srcXrb->pixmap, dstXrb->pixmap, gc,
627848b8605Smrg                srcx, srcy, width, height, destx, desty);
628848b8605Smrg   }
629848b8605Smrg   else {
630848b8605Smrg      _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
631848b8605Smrg   }
632848b8605Smrg}
633848b8605Smrg
634848b8605Smrg
635848b8605Smrg
636848b8605Smrg
637848b8605Smrg/*
638848b8605Smrg * Every driver should implement a GetString function in order to
639848b8605Smrg * return a meaningful GL_RENDERER string.
640848b8605Smrg */
641848b8605Smrgstatic const GLubyte *
642848b8605Smrgget_string( struct gl_context *ctx, GLenum name )
643848b8605Smrg{
644848b8605Smrg   (void) ctx;
645848b8605Smrg   switch (name) {
646848b8605Smrg      case GL_RENDERER:
647848b8605Smrg         return (const GLubyte *) "Mesa X11";
648848b8605Smrg      case GL_VENDOR:
649848b8605Smrg         return NULL;
650848b8605Smrg      default:
651848b8605Smrg         return NULL;
652848b8605Smrg   }
653848b8605Smrg}
654848b8605Smrg
655848b8605Smrg
656848b8605Smrg/*
657848b8605Smrg * We implement the glEnable function only because we care about
658848b8605Smrg * dither enable/disable.
659848b8605Smrg */
660848b8605Smrgstatic void
661848b8605Smrgenable( struct gl_context *ctx, GLenum pname, GLboolean state )
662848b8605Smrg{
663848b8605Smrg   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
664848b8605Smrg
665848b8605Smrg   switch (pname) {
666848b8605Smrg      case GL_DITHER:
667848b8605Smrg         if (state)
668848b8605Smrg            xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
669848b8605Smrg         else
670848b8605Smrg            xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
671848b8605Smrg         break;
672848b8605Smrg      default:
673848b8605Smrg         ;  /* silence compiler warning */
674848b8605Smrg   }
675848b8605Smrg}
676848b8605Smrg
677848b8605Smrg
678848b8605Smrg/**
679848b8605Smrg * Called when the driver should update its state, based on the new_state
680848b8605Smrg * flags.
681848b8605Smrg */
682b8e80941Smrgstatic void
683b8e80941Smrgxmesa_update_state(struct gl_context *ctx)
684848b8605Smrg{
685b8e80941Smrg   GLbitfield new_state = ctx->NewState;
686848b8605Smrg   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
687848b8605Smrg
688b8e80941Smrg   if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
689b8e80941Smrg      _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
690b8e80941Smrg
691848b8605Smrg   /* Propagate statechange information to swrast and swrast_setup
692848b8605Smrg    * modules.  The X11 driver has no internal GL-dependent state.
693848b8605Smrg    */
694848b8605Smrg   _swrast_InvalidateState( ctx, new_state );
695848b8605Smrg   _tnl_InvalidateState( ctx, new_state );
696848b8605Smrg   _swsetup_InvalidateState( ctx, new_state );
697848b8605Smrg
698848b8605Smrg   if (_mesa_is_user_fbo(ctx->DrawBuffer))
699848b8605Smrg      return;
700848b8605Smrg
701848b8605Smrg   /*
702848b8605Smrg    * GL_DITHER, GL_READ/DRAW_BUFFER, buffer binding state, etc. effect
703848b8605Smrg    * renderbuffer span/clear funcs.
704848b8605Smrg    * Check _NEW_COLOR to detect dither enable/disable.
705848b8605Smrg    */
706848b8605Smrg   if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) {
707848b8605Smrg      XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
708848b8605Smrg      struct xmesa_renderbuffer *front_xrb, *back_xrb;
709848b8605Smrg
710848b8605Smrg      front_xrb = xmbuf->frontxrb;
711848b8605Smrg      if (front_xrb) {
712848b8605Smrg         front_xrb->clearFunc = clear_pixmap;
713848b8605Smrg      }
714848b8605Smrg
715848b8605Smrg      back_xrb = xmbuf->backxrb;
716848b8605Smrg      if (back_xrb) {
717848b8605Smrg         if (xmbuf->backxrb->pixmap) {
718848b8605Smrg            back_xrb->clearFunc = clear_pixmap;
719848b8605Smrg         }
720848b8605Smrg         else {
721848b8605Smrg            switch (xmesa->xm_visual->BitsPerPixel) {
722848b8605Smrg            case 16:
723848b8605Smrg               back_xrb->clearFunc = clear_16bit_ximage;
724848b8605Smrg               break;
725848b8605Smrg            case 24:
726848b8605Smrg               back_xrb->clearFunc = clear_24bit_ximage;
727848b8605Smrg               break;
728848b8605Smrg            case 32:
729848b8605Smrg               back_xrb->clearFunc = clear_32bit_ximage;
730848b8605Smrg               break;
731848b8605Smrg            default:
732848b8605Smrg               back_xrb->clearFunc = clear_nbit_ximage;
733848b8605Smrg               break;
734848b8605Smrg            }
735848b8605Smrg         }
736848b8605Smrg      }
737848b8605Smrg   }
738848b8605Smrg}
739848b8605Smrg
740848b8605Smrg
741848b8605Smrg/**
742848b8605Smrg * Called by glViewport.
743848b8605Smrg * This is a good time for us to poll the current X window size and adjust
744848b8605Smrg * our renderbuffers to match the current window size.
745848b8605Smrg * Remember, we have no opportunity to respond to conventional
746848b8605Smrg * X Resize/StructureNotify events since the X driver has no event loop.
747848b8605Smrg * Thus, we poll.
748848b8605Smrg * Note that this trick isn't fool-proof.  If the application never calls
749848b8605Smrg * glViewport, our notion of the current window size may be incorrect.
750848b8605Smrg * That problem led to the GLX_MESA_resize_buffers extension.
751848b8605Smrg */
752848b8605Smrgstatic void
753848b8605Smrgxmesa_viewport(struct gl_context *ctx)
754848b8605Smrg{
755848b8605Smrg   XMesaContext xmctx = XMESA_CONTEXT(ctx);
756848b8605Smrg   XMesaBuffer xmdrawbuf = XMESA_BUFFER(ctx->WinSysDrawBuffer);
757848b8605Smrg   XMesaBuffer xmreadbuf = XMESA_BUFFER(ctx->WinSysReadBuffer);
758848b8605Smrg   xmesa_check_and_update_buffer_size(xmctx, xmdrawbuf);
759848b8605Smrg   xmesa_check_and_update_buffer_size(xmctx, xmreadbuf);
760848b8605Smrg}
761848b8605Smrg
762848b8605Smrg
763848b8605Smrg#if ENABLE_EXT_timer_query
764848b8605Smrg
765848b8605Smrg/*
766848b8605Smrg * The GL_EXT_timer_query extension is not enabled for the XServer
767848b8605Smrg * indirect renderer.  Not sure about how/if wrapping of gettimeofday()
768848b8605Smrg * is done, etc.
769848b8605Smrg */
770848b8605Smrg
771848b8605Smrgstruct xmesa_query_object
772848b8605Smrg{
773848b8605Smrg   struct gl_query_object Base;
774848b8605Smrg   struct timeval StartTime;
775848b8605Smrg};
776848b8605Smrg
777848b8605Smrg
778848b8605Smrgstatic struct gl_query_object *
779848b8605Smrgxmesa_new_query_object(struct gl_context *ctx, GLuint id)
780848b8605Smrg{
781848b8605Smrg   struct xmesa_query_object *q = CALLOC_STRUCT(xmesa_query_object);
782848b8605Smrg   if (q) {
783848b8605Smrg      q->Base.Id = id;
784848b8605Smrg      q->Base.Ready = GL_TRUE;
785848b8605Smrg   }
786848b8605Smrg   return &q->Base;
787848b8605Smrg}
788848b8605Smrg
789848b8605Smrg
790848b8605Smrgstatic void
791848b8605Smrgxmesa_begin_query(struct gl_context *ctx, struct gl_query_object *q)
792848b8605Smrg{
793848b8605Smrg   if (q->Target == GL_TIME_ELAPSED_EXT) {
794848b8605Smrg      struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
795848b8605Smrg      (void) gettimeofday(&xq->StartTime, NULL);
796848b8605Smrg   }
797848b8605Smrg}
798848b8605Smrg
799848b8605Smrg
800848b8605Smrg/**
801848b8605Smrg * Return the difference between the two given times in microseconds.
802848b8605Smrg */
803848b8605Smrgstatic GLuint64EXT
804848b8605Smrgtime_diff(const struct timeval *t0, const struct timeval *t1)
805848b8605Smrg{
806848b8605Smrg   GLuint64EXT seconds0 = t0->tv_sec & 0xff;  /* 0 .. 255 seconds */
807848b8605Smrg   GLuint64EXT seconds1 = t1->tv_sec & 0xff;  /* 0 .. 255 seconds */
808848b8605Smrg   GLuint64EXT nanosec0 = (seconds0 * 1000000 + t0->tv_usec) * 1000;
809848b8605Smrg   GLuint64EXT nanosec1 = (seconds1 * 1000000 + t1->tv_usec) * 1000;
810848b8605Smrg   return nanosec1 - nanosec0;
811848b8605Smrg}
812848b8605Smrg
813848b8605Smrg
814848b8605Smrgstatic void
815848b8605Smrgxmesa_end_query(struct gl_context *ctx, struct gl_query_object *q)
816848b8605Smrg{
817848b8605Smrg   if (q->Target == GL_TIME_ELAPSED_EXT) {
818848b8605Smrg      struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
819848b8605Smrg      struct timeval endTime;
820848b8605Smrg      (void) gettimeofday(&endTime, NULL);
821848b8605Smrg      /* result is in nanoseconds! */
822848b8605Smrg      q->Result = time_diff(&xq->StartTime, &endTime);
823848b8605Smrg   }
824848b8605Smrg   q->Ready = GL_TRUE;
825848b8605Smrg}
826848b8605Smrg
827848b8605Smrg#endif /* ENABLE_timer_query */
828848b8605Smrg
829848b8605Smrg
830848b8605Smrg/**
831848b8605Smrg * Initialize the device driver function table with the functions
832848b8605Smrg * we implement in this driver.
833848b8605Smrg */
834848b8605Smrgvoid
835848b8605Smrgxmesa_init_driver_functions( XMesaVisual xmvisual,
836848b8605Smrg                             struct dd_function_table *driver )
837848b8605Smrg{
838848b8605Smrg   driver->GetString = get_string;
839848b8605Smrg   driver->UpdateState = xmesa_update_state;
840848b8605Smrg   driver->Flush = finish_or_flush;
841848b8605Smrg   driver->Finish = finish_or_flush;
842848b8605Smrg   driver->ColorMask = color_mask;
843848b8605Smrg   driver->Enable = enable;
844848b8605Smrg   driver->Viewport = xmesa_viewport;
845848b8605Smrg   if (TEST_META_FUNCS) {
846848b8605Smrg      driver->Clear = _mesa_meta_Clear;
847848b8605Smrg      driver->CopyPixels = _mesa_meta_CopyPixels;
848848b8605Smrg      driver->BlitFramebuffer = _mesa_meta_and_swrast_BlitFramebuffer;
849848b8605Smrg      driver->DrawPixels = _mesa_meta_DrawPixels;
850848b8605Smrg      driver->Bitmap = _mesa_meta_Bitmap;
851848b8605Smrg   }
852848b8605Smrg   else {
853848b8605Smrg      driver->Clear = clear_buffers;
854848b8605Smrg      driver->CopyPixels = xmesa_CopyPixels;
855848b8605Smrg      if (xmvisual->undithered_pf == PF_8R8G8B &&
856848b8605Smrg          xmvisual->dithered_pf == PF_8R8G8B &&
857848b8605Smrg          xmvisual->BitsPerPixel == 32) {
858848b8605Smrg         driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
859848b8605Smrg      }
860848b8605Smrg      else if (xmvisual->undithered_pf == PF_5R6G5B) {
861848b8605Smrg         driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
862848b8605Smrg      }
863848b8605Smrg   }
864848b8605Smrg
865848b8605Smrg   driver->MapRenderbuffer = xmesa_MapRenderbuffer;
866848b8605Smrg   driver->UnmapRenderbuffer = xmesa_UnmapRenderbuffer;
867848b8605Smrg
868848b8605Smrg   driver->GenerateMipmap = _mesa_generate_mipmap;
869848b8605Smrg
870848b8605Smrg#if ENABLE_EXT_timer_query
871848b8605Smrg   driver->NewQueryObject = xmesa_new_query_object;
872848b8605Smrg   driver->BeginQuery = xmesa_begin_query;
873848b8605Smrg   driver->EndQuery = xmesa_end_query;
874848b8605Smrg#endif
875848b8605Smrg}
876848b8605Smrg
877848b8605Smrg
878848b8605Smrg#define XMESA_NEW_POINT  (_NEW_POINT | \
879848b8605Smrg                          _NEW_RENDERMODE | \
880848b8605Smrg                          _SWRAST_NEW_RASTERMASK)
881848b8605Smrg
882848b8605Smrg#define XMESA_NEW_LINE   (_NEW_LINE | \
883848b8605Smrg                          _NEW_TEXTURE | \
884848b8605Smrg                          _NEW_LIGHT | \
885848b8605Smrg                          _NEW_DEPTH | \
886848b8605Smrg                          _NEW_RENDERMODE | \
887848b8605Smrg                          _SWRAST_NEW_RASTERMASK)
888848b8605Smrg
889848b8605Smrg#define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
890848b8605Smrg                            _NEW_TEXTURE | \
891848b8605Smrg                            _NEW_LIGHT | \
892848b8605Smrg                            _NEW_DEPTH | \
893848b8605Smrg                            _NEW_RENDERMODE | \
894848b8605Smrg                            _SWRAST_NEW_RASTERMASK)
895848b8605Smrg
896848b8605Smrg
897848b8605Smrg/**
898848b8605Smrg * Extend the software rasterizer with our line/point/triangle
899848b8605Smrg * functions.
900848b8605Smrg * Called during context creation only.
901848b8605Smrg */
902848b8605Smrgvoid xmesa_register_swrast_functions( struct gl_context *ctx )
903848b8605Smrg{
904848b8605Smrg   SWcontext *swrast = SWRAST_CONTEXT( ctx );
905848b8605Smrg
906848b8605Smrg   swrast->choose_point = xmesa_choose_point;
907848b8605Smrg   swrast->choose_line = xmesa_choose_line;
908848b8605Smrg   swrast->choose_triangle = xmesa_choose_triangle;
909848b8605Smrg
910848b8605Smrg   /* XXX these lines have no net effect.  Remove??? */
911848b8605Smrg   swrast->InvalidatePointMask |= XMESA_NEW_POINT;
912848b8605Smrg   swrast->InvalidateLineMask |= XMESA_NEW_LINE;
913848b8605Smrg   swrast->InvalidateTriangleMask |= XMESA_NEW_TRIANGLE;
914848b8605Smrg}
915