blob: 81d000b3952b1a90f9306f025e9c549bba0b5965 [file] [log] [blame]
Brian Paul693f81b2000-09-07 15:40:30 +00001/*
2 * Mesa 3-D graphics library
Brian Paul94408682006-10-11 17:45:06 +00003 * Version: 6.5.2
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00004 *
Brian Paulee2339f2006-02-24 17:58:48 +00005 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00006 *
Brian Paul693f81b2000-09-07 15:40:30 +00007 * 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:
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000013 *
Brian Paul693f81b2000-09-07 15:40:30 +000014 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000016 *
Brian Paul693f81b2000-09-07 15:40:30 +000017 * 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 */
Brian Paul98fc9b32003-03-27 17:51:33 +000024
Brian Paul693f81b2000-09-07 15:40:30 +000025
Brian Pauld21fa9c2006-10-14 22:52:17 +000026/**
27 * \file xm_dd.h
28 * General device driver functions for Xlib driver.
29 */
30
Brian Paul693f81b2000-09-07 15:40:30 +000031#include "glxheader.h"
Brian Paul374e7fd2008-09-18 13:46:47 -060032#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"
Brian Paulb70610b2011-02-28 18:24:35 -070044#include "main/pbo.h"
Brian Paul374e7fd2008-09-18 13:46:47 -060045#include "main/state.h"
46#include "main/texobj.h"
47#include "main/teximage.h"
48#include "main/texstore.h"
49#include "main/texformat.h"
Keith Whitwellec058582000-11-05 18:26:12 +000050#include "swrast/swrast.h"
Brian Paulde0dd652003-11-29 19:36:08 +000051#include "swrast/s_context.h"
Keith Whitwellec058582000-11-05 18:26:12 +000052#include "swrast_setup/swrast_setup.h"
Keith Whitwell23caf202000-11-16 21:05:34 +000053#include "tnl/tnl.h"
Keith Whitwell70989242001-03-19 02:25:35 +000054#include "tnl/t_context.h"
Brian Paul8126dfa2009-08-31 19:29:24 -060055#include "drivers/common/meta.h"
Brian Paul374e7fd2008-09-18 13:46:47 -060056#include "xmesaP.h"
Brian Paul8e39ad22001-02-06 21:42:48 +000057
Brian Pauld5e4f292004-03-04 16:22:01 +000058
59
60/*
61 * Dithering kernels and lookup tables.
62 */
63
64const 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
71const 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
86const 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
Brian Paul693f81b2000-09-07 15:40:30 +000094static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -040095finish_or_flush( struct gl_context *ctx )
Brian Paul693f81b2000-09-07 15:40:30 +000096{
Brian Paul1e24d332003-04-01 17:28:10 +000097 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paul693f81b2000-09-07 15:40:30 +000098 if (xmesa) {
99 _glthread_LOCK_MUTEX(_xmesa_lock);
100 XSync( xmesa->display, False );
101 _glthread_UNLOCK_MUTEX(_xmesa_lock);
102 }
Brian Paul693f81b2000-09-07 15:40:30 +0000103}
104
105
Brian Paul693f81b2000-09-07 15:40:30 +0000106static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400107clear_color( struct gl_context *ctx, const GLfloat color[4] )
Brian Paul693f81b2000-09-07 15:40:30 +0000108{
Brian Paule4b23562005-05-04 20:11:35 +0000109 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 }
Brian Paul693f81b2000-09-07 15:40:30 +0000128}
129
130
131
Brian Paul693f81b2000-09-07 15:40:30 +0000132/* Implements glColorMask() */
133static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400134color_mask(struct gl_context *ctx,
Brian Paul693f81b2000-09-07 15:40:30 +0000135 GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
136{
Brian Paul1e24d332003-04-01 17:28:10 +0000137 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paulc7a5d522006-03-28 15:21:44 +0000138 XMesaBuffer xmbuf;
Brian Paulc3ed27e2010-10-13 08:32:08 -0600139 const int xclass = xmesa->xm_visual->visualType;
Brian Paul693f81b2000-09-07 15:40:30 +0000140 (void) amask;
141
Brian Paulc7a5d522006-03-28 15:21:44 +0000142 if (ctx->DrawBuffer->Name != 0)
143 return;
144
145 xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
146
Ian Romanick304d3aa2004-02-19 00:57:04 +0000147 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
Brian Paul693f81b2000-09-07 15:40:30 +0000148 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 }
Brian Paule4b23562005-05-04 20:11:35 +0000158 XMesaSetPlaneMask( xmesa->display, xmbuf->cleargc, m );
Brian Paul693f81b2000-09-07 15:40:30 +0000159 }
160}
161
162
Brian Paul693f81b2000-09-07 15:40:30 +0000163
164/**********************************************************************/
165/*** glClear implementations ***/
166/**********************************************************************/
167
168
Brian Paule4b23562005-05-04 20:11:35 +0000169/**
170 * Clear the front or back color buffer, if it's implemented with a pixmap.
171 */
Brian Paul693f81b2000-09-07 15:40:30 +0000172static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400173clear_pixmap(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
Brian Paule4b23562005-05-04 20:11:35 +0000174 GLint x, GLint y, GLint width, GLint height)
Brian Paul693f81b2000-09-07 15:40:30 +0000175{
Brian Paul1e24d332003-04-01 17:28:10 +0000176 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paule4b23562005-05-04 20:11:35 +0000177 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
178
Brian Paulb1d0ac62005-05-06 15:23:54 +0000179 assert(xmbuf);
180 assert(xrb->pixmap);
181 assert(xmesa);
182 assert(xmesa->display);
183 assert(xrb->pixmap);
184 assert(xmbuf->cleargc);
Brian Paule4b23562005-05-04 20:11:35 +0000185
Brian Paulec99e712006-10-18 20:03:20 +0000186 XMesaFillRectangle( xmesa->display, xrb->pixmap, xmbuf->cleargc,
187 x, xrb->Base.Height - y - height,
188 width, height );
Brian Paul693f81b2000-09-07 15:40:30 +0000189}
190
191
192static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400193clear_8bit_ximage( struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
Brian Paulec99e712006-10-18 20:03:20 +0000194 GLint x, GLint y, GLint width, GLint height )
Brian Paul693f81b2000-09-07 15:40:30 +0000195{
Brian Paul1e24d332003-04-01 17:28:10 +0000196 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paulec99e712006-10-18 20:03:20 +0000197 GLint i;
198 for (i = 0; i < height; i++) {
199 GLubyte *ptr = PIXEL_ADDR1(xrb, x, y + i);
Brian Paul2240ba12010-02-19 08:12:31 -0700200 memset( ptr, xmesa->clearpixel, width );
Brian Paul693f81b2000-09-07 15:40:30 +0000201 }
202}
203
204
205static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400206clear_HPCR_ximage( struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
Brian Paulec99e712006-10-18 20:03:20 +0000207 GLint x, GLint y, GLint width, GLint height )
Brian Paul693f81b2000-09-07 15:40:30 +0000208{
Brian Paul1e24d332003-04-01 17:28:10 +0000209 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paulec99e712006-10-18 20:03:20 +0000210 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;
Brian Paul693f81b2000-09-07 15:40:30 +0000217 }
Brian Paulec99e712006-10-18 20:03:20 +0000218 for (j = x; j < x + width; j++) {
219 *ptr = sptr[j&15];
220 ptr++;
Brian Paul693f81b2000-09-07 15:40:30 +0000221 }
222 }
223}
224
225
226static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400227clear_16bit_ximage( struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
Brian Paulec99e712006-10-18 20:03:20 +0000228 GLint x, GLint y, GLint width, GLint height)
Brian Paul693f81b2000-09-07 15:40:30 +0000229{
Brian Paul1e24d332003-04-01 17:28:10 +0000230 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paulec99e712006-10-18 20:03:20 +0000231 GLuint pixel = (GLuint) xmesa->clearpixel;
232 GLint i, j;
Brian Paule4b23562005-05-04 20:11:35 +0000233
Brian Paul693f81b2000-09-07 15:40:30 +0000234 if (xmesa->swapbytes) {
235 pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
236 }
Brian Paule4b23562005-05-04 20:11:35 +0000237
Brian Paulec99e712006-10-18 20:03:20 +0000238 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;
Brian Paul693f81b2000-09-07 15:40:30 +0000242 }
243 }
244}
245
246
247/* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
248static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400249clear_24bit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
Brian Paulec99e712006-10-18 20:03:20 +0000250 GLint x, GLint y, GLint width, GLint height)
Brian Paul693f81b2000-09-07 15:40:30 +0000251{
Brian Paul1e24d332003-04-01 17:28:10 +0000252 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paul693f81b2000-09-07 15:40:30 +0000253 const GLubyte r = xmesa->clearcolor[0];
254 const GLubyte g = xmesa->clearcolor[1];
255 const GLubyte b = xmesa->clearcolor[2];
Brian Paul693f81b2000-09-07 15:40:30 +0000256
Brian Paulec99e712006-10-18 20:03:20 +0000257 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);
Brian Paul2240ba12010-02-19 08:12:31 -0700262 memset(ptr3, r, 3 * width);
Brian Paul693f81b2000-09-07 15:40:30 +0000263 }
264 }
265 else {
Brian Paulec99e712006-10-18 20:03:20 +0000266 /* 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++;
Brian Paul693f81b2000-09-07 15:40:30 +0000275 }
Brian Paul693f81b2000-09-07 15:40:30 +0000276 }
277 }
278}
279
280
281static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400282clear_32bit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
Brian Paulec99e712006-10-18 20:03:20 +0000283 GLint x, GLint y, GLint width, GLint height)
Brian Paul693f81b2000-09-07 15:40:30 +0000284{
Brian Paul1e24d332003-04-01 17:28:10 +0000285 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paul9d205e32001-04-03 16:19:54 +0000286 register GLuint pixel = (GLuint) xmesa->clearpixel;
Brian Paule4b23562005-05-04 20:11:35 +0000287
Brian Paul41b97562006-01-09 16:59:30 +0000288 if (!xrb->ximage)
289 return;
290
Brian Paul9d205e32001-04-03 16:19:54 +0000291 if (xmesa->swapbytes) {
292 pixel = ((pixel >> 24) & 0x000000ff)
Brian Paul693f81b2000-09-07 15:40:30 +0000293 | ((pixel >> 8) & 0x0000ff00)
294 | ((pixel << 8) & 0x00ff0000)
295 | ((pixel << 24) & 0xff000000);
Brian Paul9d205e32001-04-03 16:19:54 +0000296 }
Brian Paule4b23562005-05-04 20:11:35 +0000297
Brian Paulec99e712006-10-18 20:03:20 +0000298 if (width == xrb->Base.Width && height == xrb->Base.Height) {
299 /* clearing whole buffer */
Brian Paule4b23562005-05-04 20:11:35 +0000300 const GLuint n = xrb->Base.Width * xrb->Base.Height;
301 GLuint *ptr4 = (GLuint *) xrb->ximage->data;
302 if (pixel == 0) {
Brian Paulec99e712006-10-18 20:03:20 +0000303 /* common case */
Kenneth Graunke26f8fad2010-02-18 23:51:00 -0800304 memset(ptr4, pixel, 4 * n);
Brian Paul693f81b2000-09-07 15:40:30 +0000305 }
306 else {
Brian Paule4b23562005-05-04 20:11:35 +0000307 GLuint i;
308 for (i = 0; i < n; i++)
309 ptr4[i] = pixel;
Brian Paul693f81b2000-09-07 15:40:30 +0000310 }
311 }
312 else {
Brian Paulec99e712006-10-18 20:03:20 +0000313 /* clearing scissored region */
Brian Paule4b23562005-05-04 20:11:35 +0000314 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;
Brian Paul693f81b2000-09-07 15:40:30 +0000319 }
320 }
321 }
322}
323
324
325static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400326clear_nbit_ximage(struct gl_context *ctx, struct xmesa_renderbuffer *xrb,
Brian Paulec99e712006-10-18 20:03:20 +0000327 GLint x, GLint y, GLint width, GLint height)
Brian Paul693f81b2000-09-07 15:40:30 +0000328{
Brian Paul1e24d332003-04-01 17:28:10 +0000329 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paule4b23562005-05-04 20:11:35 +0000330 XMesaImage *img = xrb->ximage;
331 GLint i, j;
Brian Paul29926a12004-11-27 21:20:37 +0000332
Brian Paul29926a12004-11-27 21:20:37 +0000333 /* TODO: optimize this */
Brian Paule4b23562005-05-04 20:11:35 +0000334 y = YFLIP(xrb, y);
Brian Paul29926a12004-11-27 21:20:37 +0000335 for (j = 0; j < height; j++) {
336 for (i = 0; i < width; i++) {
337 XMesaPutPixel(img, x+i, y-j, xmesa->clearpixel);
Brian Paul693f81b2000-09-07 15:40:30 +0000338 }
339 }
340}
341
342
343
Keith Whitwelld98fdad2001-01-29 20:56:32 +0000344static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400345clear_buffers(struct gl_context *ctx, GLbitfield buffers)
Brian Paul693f81b2000-09-07 15:40:30 +0000346{
Brian Paule4b23562005-05-04 20:11:35 +0000347 if (ctx->DrawBuffer->Name == 0) {
348 /* this is a window system framebuffer */
Brian Paulfd5511d2009-12-29 16:17:14 -0700349 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask[0];
Brian Paul444cd292006-04-27 02:47:50 +0000350 XMesaBuffer b = XMESA_BUFFER(ctx->DrawBuffer);
Brian Paulec99e712006-10-18 20:03:20 +0000351 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;
Brian Paul693f81b2000-09-07 15:40:30 +0000355
Brian Paule4b23562005-05-04 20:11:35 +0000356 /* we can't handle color or index masking */
357 if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
Alan Hourihane6d104cb2006-11-02 12:02:13 +0000358 if (buffers & BUFFER_BIT_FRONT_LEFT) {
Brian Paule4b23562005-05-04 20:11:35 +0000359 /* clear front color buffer */
Brian Paul444cd292006-04-27 02:47:50 +0000360 struct gl_renderbuffer *frontRb
361 = ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
362 if (b->frontxrb == xmesa_renderbuffer(frontRb)) {
Brian Paule4b23562005-05-04 20:11:35 +0000363 /* renderbuffer is not wrapped - great! */
Brian Paulec99e712006-10-18 20:03:20 +0000364 b->frontxrb->clearFunc(ctx, b->frontxrb, x, y, width, height);
Alan Hourihane6d104cb2006-11-02 12:02:13 +0000365 buffers &= ~BUFFER_BIT_FRONT_LEFT;
Brian Paule4b23562005-05-04 20:11:35 +0000366 }
367 else {
368 /* we can't directly clear an alpha-wrapped color buffer */
369 }
370 }
Alan Hourihane6d104cb2006-11-02 12:02:13 +0000371 if (buffers & BUFFER_BIT_BACK_LEFT) {
Brian Paule4b23562005-05-04 20:11:35 +0000372 /* clear back color buffer */
Brian Paul444cd292006-04-27 02:47:50 +0000373 struct gl_renderbuffer *backRb
374 = ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
375 if (b->backxrb == xmesa_renderbuffer(backRb)) {
Brian Paule4b23562005-05-04 20:11:35 +0000376 /* renderbuffer is not wrapped - great! */
Brian Paulec99e712006-10-18 20:03:20 +0000377 b->backxrb->clearFunc(ctx, b->backxrb, x, y, width, height);
Alan Hourihane6d104cb2006-11-02 12:02:13 +0000378 buffers &= ~BUFFER_BIT_BACK_LEFT;
Brian Paule4b23562005-05-04 20:11:35 +0000379 }
380 }
Keith Whitwelld98fdad2001-01-29 20:56:32 +0000381 }
Brian Paul693f81b2000-09-07 15:40:30 +0000382 }
Alan Hourihane6d104cb2006-11-02 12:02:13 +0000383 if (buffers)
384 _swrast_Clear(ctx, buffers);
Brian Paul693f81b2000-09-07 15:40:30 +0000385}
386
387
Brian15f00152008-02-16 09:56:54 -0700388/* 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 */
394static GLboolean
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400395can_do_DrawPixels_8R8G8B(struct gl_context *ctx, GLenum format, GLenum type)
Brian15f00152008-02-16 09:56:54 -0700396{
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 */
Brian Paul45e76d22009-10-08 20:27:27 -0600415 _mesa_get_format_bits(xrb->Base.Format, GL_ALPHA_BITS) == 0) {
Brian15f00152008-02-16 09:56:54 -0700416 return GL_TRUE;
417 }
418 }
419 }
420 }
421 return GL_FALSE;
422}
423
Brian Paul1d7b75c2003-12-04 15:29:10 +0000424
Brian Paulde0dd652003-11-29 19:36:08 +0000425/**
Brian Paul693f81b2000-09-07 15:40:30 +0000426 * 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.
Brian Paul693f81b2000-09-07 15:40:30 +0000429 */
Brian Paulde0dd652003-11-29 19:36:08 +0000430static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400431xmesa_DrawPixels_8R8G8B( struct gl_context *ctx,
Brian Paulde0dd652003-11-29 19:36:08 +0000432 GLint x, GLint y, GLsizei width, GLsizei height,
433 GLenum format, GLenum type,
434 const struct gl_pixelstore_attrib *unpack,
435 const GLvoid *pixels )
Brian Paul693f81b2000-09-07 15:40:30 +0000436{
Brian15f00152008-02-16 09:56:54 -0700437 if (can_do_DrawPixels_8R8G8B(ctx, format, type)) {
438 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
439 struct gl_pixelstore_attrib clippedUnpack = *unpack;
Brian Paul693f81b2000-09-07 15:40:30 +0000440 int dstX = x;
441 int dstY = y;
442 int w = width;
443 int h = height;
Brian Paul7a6b71e2004-03-13 18:21:40 +0000444
Brian15f00152008-02-16 09:56:54 -0700445 if (swrast->NewState)
446 _swrast_validate_derived( ctx );
Brian Paul94408682006-10-11 17:45:06 +0000447
Brian Paul6b329b92011-04-26 14:54:41 -0600448 if (_mesa_is_bufferobj(unpack->BufferObj)) {
Brian Paulba164c42004-10-31 15:49:59 +0000449 /* unpack from PBO */
450 GLubyte *buf;
Brian Paul60909382004-11-10 15:46:52 +0000451 if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
Brian Paul6b329b92011-04-26 14:54:41 -0600452 format, type, INT_MAX, pixels)) {
Brian Paulba164c42004-10-31 15:49:59 +0000453 _mesa_error(ctx, GL_INVALID_OPERATION,
454 "glDrawPixels(invalid PBO access)");
455 return;
456 }
Ian Romanick28249bd2011-08-21 18:34:27 -0700457 buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0,
458 unpack->BufferObj->Size,
459 GL_MAP_READ_BIT,
460 unpack->BufferObj);
Brian Paulba164c42004-10-31 15:49:59 +0000461 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 }
Brian Paul7a6b71e2004-03-13 18:21:40 +0000469
Brian Paul1ad7b992005-09-28 02:29:50 +0000470 if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
Brian15f00152008-02-16 09:56:54 -0700471 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
Brian Paulde0dd652003-11-29 19:36:08 +0000487 /* 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 */
Brian Paul2240ba12010-02-19 08:12:31 -0700491 memset(&ximage, 0, sizeof(XMesaImage));
Brian Paul693f81b2000-09-07 15:40:30 +0000492 ximage.width = width;
493 ximage.height = height;
494 ximage.format = ZPixmap;
Brian Paulde0dd652003-11-29 19:36:08 +0000495 ximage.data = (char *) pixels
496 + ((srcY + h - 1) * rowLength + srcX) * 4;
Brian Paul693f81b2000-09-07 15:40:30 +0000497 ximage.byte_order = LSBFirst;
498 ximage.bitmap_unit = 32;
499 ximage.bitmap_bit_order = LSBFirst;
500 ximage.bitmap_pad = 32;
Brian15f00152008-02-16 09:56:54 -0700501 ximage.depth = 32;
Brian Paul693f81b2000-09-07 15:40:30 +0000502 ximage.bits_per_pixel = 32;
Brian15f00152008-02-16 09:56:54 -0700503 ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */
Brian Paul1d7b75c2003-12-04 15:29:10 +0000504 /* it seems we don't need to set the ximage.red/green/blue_mask fields */
Brian Paulde0dd652003-11-29 19:36:08 +0000505 /* flip Y axis for dest position */
Brian Paule4b23562005-05-04 20:11:35 +0000506 dstY = YFLIP(xrb, dstY) - h + 1;
507 XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
Brian Paul693f81b2000-09-07 15:40:30 +0000508 }
Brian Paulba164c42004-10-31 15:49:59 +0000509
Brian Paul6b329b92011-04-26 14:54:41 -0600510 if (_mesa_is_bufferobj(unpack->BufferObj)) {
Ian Romanick56f0c002011-08-21 16:59:30 -0700511 ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj);
Brian Paulba164c42004-10-31 15:49:59 +0000512 }
Brian Paul693f81b2000-09-07 15:40:30 +0000513 }
Brian Paulde0dd652003-11-29 19:36:08 +0000514 else {
515 /* software fallback */
516 _swrast_DrawPixels(ctx, x, y, width, height,
517 format, type, unpack, pixels);
518 }
Brian Paul693f81b2000-09-07 15:40:30 +0000519}
Brian Paulde0dd652003-11-29 19:36:08 +0000520
521
522
523/**
Brian15f00152008-02-16 09:56:54 -0700524 * Check if we can do an optimized glDrawPixels into an 5R6G5B visual.
525 */
526static GLboolean
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400527can_do_DrawPixels_5R6G5B(struct gl_context *ctx, GLenum format, GLenum type)
Brian15f00152008-02-16 09:56:54 -0700528{
529 if (format == GL_RGB &&
530 type == GL_UNSIGNED_SHORT_5_6_5 &&
531 !ctx->Color.DitherFlag && /* no dithering */
532 ctx->DrawBuffer &&
533 ctx->DrawBuffer->Name == 0 &&
534 ctx->Pixel.ZoomX == 1.0 && /* no zooming */
535 ctx->Pixel.ZoomY == 1.0 &&
536 ctx->_ImageTransferState == 0 /* no color tables, scale/bias, etc */) {
537 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
538
539 if (swrast->NewState)
540 _swrast_validate_derived( ctx );
541
542 if ((swrast->_RasterMask & ~CLIP_BIT) == 0) /* no blend, z-test, etc */ {
543 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
544 if (rb) {
545 struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb->Wrapped);
546 if (xrb &&
547 xrb->pixmap && /* drawing to pixmap or window */
Brian Paul45e76d22009-10-08 20:27:27 -0600548 _mesa_get_format_bits(xrb->Base.Format, GL_ALPHA_BITS) == 0) {
Brian15f00152008-02-16 09:56:54 -0700549 return GL_TRUE;
550 }
551 }
552 }
553 }
554 return GL_FALSE;
555}
556
557
558/**
Brian Paulde0dd652003-11-29 19:36:08 +0000559 * This function implements glDrawPixels() with an XPutImage call when
560 * drawing to the front buffer (X Window drawable). The image format
561 * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to
562 * match the PF_5R6G5B pixel format.
563 */
564static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400565xmesa_DrawPixels_5R6G5B( struct gl_context *ctx,
Brian Paulde0dd652003-11-29 19:36:08 +0000566 GLint x, GLint y, GLsizei width, GLsizei height,
567 GLenum format, GLenum type,
568 const struct gl_pixelstore_attrib *unpack,
569 const GLvoid *pixels )
570{
Brian15f00152008-02-16 09:56:54 -0700571 if (can_do_DrawPixels_5R6G5B(ctx, format, type)) {
572 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
573 struct gl_pixelstore_attrib clippedUnpack = *unpack;
Brian Paulde0dd652003-11-29 19:36:08 +0000574 int dstX = x;
575 int dstY = y;
576 int w = width;
577 int h = height;
Brian Paul7a6b71e2004-03-13 18:21:40 +0000578
Brian15f00152008-02-16 09:56:54 -0700579 if (swrast->NewState)
580 _swrast_validate_derived( ctx );
581
Brian Paul6b329b92011-04-26 14:54:41 -0600582 if (_mesa_is_bufferobj(unpack->BufferObj)) {
Brian Paulba164c42004-10-31 15:49:59 +0000583 /* unpack from PBO */
584 GLubyte *buf;
Brian Paul60909382004-11-10 15:46:52 +0000585 if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
Brian Paul6b329b92011-04-26 14:54:41 -0600586 format, type, INT_MAX, pixels)) {
Brian Paulba164c42004-10-31 15:49:59 +0000587 _mesa_error(ctx, GL_INVALID_OPERATION,
588 "glDrawPixels(invalid PBO access)");
589 return;
590 }
Brian Paulc3ad95e2011-08-24 07:55:04 -0600591 buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0,
Ian Romanick28249bd2011-08-21 18:34:27 -0700592 unpack->BufferObj->Size,
593 GL_MAP_READ_BIT,
594 unpack->BufferObj);
Brian Paulba164c42004-10-31 15:49:59 +0000595 if (!buf) {
596 /* buffer is already mapped - that's an error */
597 _mesa_error(ctx, GL_INVALID_OPERATION,
598 "glDrawPixels(PBO is mapped)");
599 return;
600 }
601 pixels = ADD_POINTERS(buf, pixels);
602 }
Brian Paul7a6b71e2004-03-13 18:21:40 +0000603
Brian Paul1ad7b992005-09-28 02:29:50 +0000604 if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
Brian15f00152008-02-16 09:56:54 -0700605 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
606 XMesaDisplay *dpy = xmesa->xm_visual->display;
607 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
608 const XMesaGC gc = xmbuf->cleargc; /* effected by glColorMask */
609 struct xmesa_renderbuffer *xrb
610 = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
611 const int srcX = clippedUnpack.SkipPixels;
612 const int srcY = clippedUnpack.SkipRows;
613 const int rowLength = clippedUnpack.RowLength;
614 XMesaImage ximage;
615
616 ASSERT(xmesa->xm_visual->undithered_pf == PF_5R6G5B);
617 ASSERT(dpy);
618 ASSERT(gc);
619
Brian Paulde0dd652003-11-29 19:36:08 +0000620 /* This is a little tricky since all coordinates up to now have
621 * been in the OpenGL bottom-to-top orientation. X is top-to-bottom
622 * so we have to carefully compute the Y coordinates/addresses here.
623 */
Brian Paul2240ba12010-02-19 08:12:31 -0700624 memset(&ximage, 0, sizeof(XMesaImage));
Brian Paulde0dd652003-11-29 19:36:08 +0000625 ximage.width = width;
626 ximage.height = height;
627 ximage.format = ZPixmap;
628 ximage.data = (char *) pixels
629 + ((srcY + h - 1) * rowLength + srcX) * 2;
630 ximage.byte_order = LSBFirst;
Brian Paul1d7b75c2003-12-04 15:29:10 +0000631 ximage.bitmap_unit = 16;
Brian Paulde0dd652003-11-29 19:36:08 +0000632 ximage.bitmap_bit_order = LSBFirst;
Brian Paul1d7b75c2003-12-04 15:29:10 +0000633 ximage.bitmap_pad = 16;
Brian Paulde0dd652003-11-29 19:36:08 +0000634 ximage.depth = 16;
Brian Paulde0dd652003-11-29 19:36:08 +0000635 ximage.bits_per_pixel = 16;
Brian15f00152008-02-16 09:56:54 -0700636 ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */
Brian Paul1d7b75c2003-12-04 15:29:10 +0000637 /* it seems we don't need to set the ximage.red/green/blue_mask fields */
Brian Paulde0dd652003-11-29 19:36:08 +0000638 /* flip Y axis for dest position */
Brian Paule4b23562005-05-04 20:11:35 +0000639 dstY = YFLIP(xrb, dstY) - h + 1;
640 XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
Brian Paulde0dd652003-11-29 19:36:08 +0000641 }
Brian Paulba164c42004-10-31 15:49:59 +0000642
643 if (unpack->BufferObj->Name) {
Ian Romanick56f0c002011-08-21 16:59:30 -0700644 ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj);
Brian Paulba164c42004-10-31 15:49:59 +0000645 }
Brian Paulde0dd652003-11-29 19:36:08 +0000646 }
647 else {
648 /* software fallback */
649 _swrast_DrawPixels(ctx, x, y, width, height,
650 format, type, unpack, pixels);
651 }
652}
653
654
Brian15f00152008-02-16 09:56:54 -0700655/**
656 * Determine if we can do an optimized glCopyPixels.
657 */
658static GLboolean
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400659can_do_CopyPixels(struct gl_context *ctx, GLenum type)
Brian15f00152008-02-16 09:56:54 -0700660{
661 if (type == GL_COLOR &&
662 ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
663 ctx->Pixel.ZoomX == 1.0 && /* no zooming */
664 ctx->Pixel.ZoomY == 1.0 &&
665 ctx->Color.DrawBuffer[0] == GL_FRONT && /* copy to front buf */
666 ctx->Pixel.ReadBuffer == GL_FRONT && /* copy from front buf */
667 ctx->ReadBuffer->_ColorReadBuffer &&
668 ctx->DrawBuffer->_ColorDrawBuffers[0]) {
669 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
670
671 if (swrast->NewState)
672 _swrast_validate_derived( ctx );
673
674 if ((swrast->_RasterMask & ~CLIP_BIT) == 0x0 &&
675 ctx->ReadBuffer &&
676 ctx->ReadBuffer->_ColorReadBuffer &&
677 ctx->DrawBuffer &&
678 ctx->DrawBuffer->_ColorDrawBuffers[0]) {
679 struct xmesa_renderbuffer *srcXrb
680 = xmesa_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer->Wrapped);
681 struct xmesa_renderbuffer *dstXrb
682 = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
683 if (srcXrb->pixmap && dstXrb->pixmap) {
684 return GL_TRUE;
685 }
686 }
687 }
688 return GL_FALSE;
689}
690
Brian Paulde0dd652003-11-29 19:36:08 +0000691
692/**
693 * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
694 * for the color buffer. Don't support zooming, pixel transfer, etc.
695 * We do support copying from one window to another, ala glXMakeCurrentRead.
696 */
697static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400698xmesa_CopyPixels( struct gl_context *ctx,
Brian Paulde0dd652003-11-29 19:36:08 +0000699 GLint srcx, GLint srcy, GLsizei width, GLsizei height,
700 GLint destx, GLint desty, GLenum type )
701{
Brian15f00152008-02-16 09:56:54 -0700702 if (can_do_CopyPixels(ctx, type)) {
703 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
704 XMesaDisplay *dpy = xmesa->xm_visual->display;
705 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
706 const XMesaGC gc = xmbuf->cleargc; /* effected by glColorMask */
707 struct xmesa_renderbuffer *srcXrb
708 = xmesa_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer->Wrapped);
709 struct xmesa_renderbuffer *dstXrb
710 = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
Brian2a077502008-01-22 21:11:55 -0700711
Brian15f00152008-02-16 09:56:54 -0700712 ASSERT(dpy);
713 ASSERT(gc);
Brian Paulde0dd652003-11-29 19:36:08 +0000714
Brian Paulde0dd652003-11-29 19:36:08 +0000715 /* Note: we don't do any special clipping work here. We could,
716 * but X will do it for us.
717 */
Brian Paule4b23562005-05-04 20:11:35 +0000718 srcy = YFLIP(srcXrb, srcy) - height + 1;
719 desty = YFLIP(dstXrb, desty) - height + 1;
720 XCopyArea(dpy, srcXrb->pixmap, dstXrb->pixmap, gc,
Brian Paulde0dd652003-11-29 19:36:08 +0000721 srcx, srcy, width, height, destx, desty);
722 }
723 else {
724 _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
725 }
726}
Brian15f00152008-02-16 09:56:54 -0700727
Brian Paulde0dd652003-11-29 19:36:08 +0000728
Brian Paul693f81b2000-09-07 15:40:30 +0000729
730
Brian Paul57d882b2003-09-17 16:06:49 +0000731/*
732 * Every driver should implement a GetString function in order to
733 * return a meaningful GL_RENDERER string.
734 */
Brian Paul693f81b2000-09-07 15:40:30 +0000735static const GLubyte *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400736get_string( struct gl_context *ctx, GLenum name )
Brian Paul693f81b2000-09-07 15:40:30 +0000737{
738 (void) ctx;
739 switch (name) {
740 case GL_RENDERER:
Brian Paul693f81b2000-09-07 15:40:30 +0000741 return (const GLubyte *) "Mesa X11";
Brian Paul693f81b2000-09-07 15:40:30 +0000742 case GL_VENDOR:
Brian Paul693f81b2000-09-07 15:40:30 +0000743 return NULL;
Brian Paul693f81b2000-09-07 15:40:30 +0000744 default:
745 return NULL;
746 }
747}
748
749
Brian Paul57d882b2003-09-17 16:06:49 +0000750/*
751 * We implement the glEnable function only because we care about
752 * dither enable/disable.
753 */
Brian Paul7f7b2052000-09-08 21:44:55 +0000754static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400755enable( struct gl_context *ctx, GLenum pname, GLboolean state )
Brian Paul7f7b2052000-09-08 21:44:55 +0000756{
Brian Paul1e24d332003-04-01 17:28:10 +0000757 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paul7f7b2052000-09-08 21:44:55 +0000758
759 switch (pname) {
760 case GL_DITHER:
761 if (state)
762 xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
763 else
764 xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
765 break;
766 default:
767 ; /* silence compiler warning */
768 }
769}
770
771
Brian Paule4b23562005-05-04 20:11:35 +0000772static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400773clear_color_HPCR_ximage( struct gl_context *ctx, const GLfloat color[4] )
Brian Paule4b23562005-05-04 20:11:35 +0000774{
775 int i;
776 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
777
778 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
779 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
780 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
781 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
782
783 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
784 /* black is black */
Brian Paul2240ba12010-02-19 08:12:31 -0700785 memset( xmesa->xm_visual->hpcr_clear_ximage_pattern, 0x0 ,
Brian Paule4b23562005-05-04 20:11:35 +0000786 sizeof(xmesa->xm_visual->hpcr_clear_ximage_pattern));
787 }
788 else {
789 /* build clear pattern */
790 for (i=0; i<16; i++) {
791 xmesa->xm_visual->hpcr_clear_ximage_pattern[0][i] =
792 DITHER_HPCR(i, 0,
793 xmesa->clearcolor[0],
794 xmesa->clearcolor[1],
795 xmesa->clearcolor[2]);
796 xmesa->xm_visual->hpcr_clear_ximage_pattern[1][i] =
797 DITHER_HPCR(i, 1,
798 xmesa->clearcolor[0],
799 xmesa->clearcolor[1],
800 xmesa->clearcolor[2]);
801 }
802 }
803}
804
805
806static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400807clear_color_HPCR_pixmap( struct gl_context *ctx, const GLfloat color[4] )
Brian Paule4b23562005-05-04 20:11:35 +0000808{
809 int i;
810 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
811
812 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
813 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
814 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
815 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
816
817 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
818 /* black is black */
819 for (i=0; i<16; i++) {
820 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0, 0);
821 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1, 0);
822 }
823 }
824 else {
825 for (i=0; i<16; i++) {
826 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0,
827 DITHER_HPCR(i, 0,
828 xmesa->clearcolor[0],
829 xmesa->clearcolor[1],
830 xmesa->clearcolor[2]));
831 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1,
832 DITHER_HPCR(i, 1,
833 xmesa->clearcolor[0],
834 xmesa->clearcolor[1],
835 xmesa->clearcolor[2]));
836 }
837 }
838 /* change tile pixmap content */
839 XMesaPutImage(xmesa->display,
840 (XMesaDrawable)xmesa->xm_visual->hpcr_clear_pixmap,
841 XMESA_BUFFER(ctx->DrawBuffer)->cleargc,
842 xmesa->xm_visual->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
843}
844
845
846/**
Brian Paulc2901e42006-01-09 17:56:55 +0000847 * Called when the driver should update its state, based on the new_state
Brian Paule4b23562005-05-04 20:11:35 +0000848 * flags.
849 */
850void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400851xmesa_update_state( struct gl_context *ctx, GLbitfield new_state )
Brian Paul693f81b2000-09-07 15:40:30 +0000852{
Brian Paul1e24d332003-04-01 17:28:10 +0000853 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
Brian Paul693f81b2000-09-07 15:40:30 +0000854
Brian Paulf9051452005-04-18 17:48:25 +0000855 /* Propagate statechange information to swrast and swrast_setup
Keith Whitwellec058582000-11-05 18:26:12 +0000856 * modules. The X11 driver has no internal GL-dependent state.
Brian Paul693f81b2000-09-07 15:40:30 +0000857 */
Keith Whitwellcab974c2000-12-26 05:09:27 +0000858 _swrast_InvalidateState( ctx, new_state );
Keith Whitwellcab974c2000-12-26 05:09:27 +0000859 _tnl_InvalidateState( ctx, new_state );
Keith Whitwell48f5dea2006-10-30 16:56:56 +0000860 _vbo_InvalidateState( ctx, new_state );
Keith Whitwellcab974c2000-12-26 05:09:27 +0000861 _swsetup_InvalidateState( ctx, new_state );
Keith Whitwellec058582000-11-05 18:26:12 +0000862
Brian Paule4b23562005-05-04 20:11:35 +0000863 if (ctx->DrawBuffer->Name != 0)
864 return;
Keith Whitwellec058582000-11-05 18:26:12 +0000865
Brian Paulc2901e42006-01-09 17:56:55 +0000866 /*
Brian Paulee2339f2006-02-24 17:58:48 +0000867 * GL_DITHER, GL_READ/DRAW_BUFFER, buffer binding state, etc. effect
868 * renderbuffer span/clear funcs.
Brian Paul62043b22009-05-01 18:31:04 -0600869 * Check _NEW_COLOR to detect dither enable/disable.
Brian Paulc2901e42006-01-09 17:56:55 +0000870 */
Brian Paul62043b22009-05-01 18:31:04 -0600871 if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) {
Brian Paulfaee3f02006-04-26 03:19:54 +0000872 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
Brian Paulc2901e42006-01-09 17:56:55 +0000873 struct xmesa_renderbuffer *front_xrb, *back_xrb;
Brian Paule4b23562005-05-04 20:11:35 +0000874
Brian Paulfaee3f02006-04-26 03:19:54 +0000875 front_xrb = xmbuf->frontxrb;
Brian Paulc2901e42006-01-09 17:56:55 +0000876 if (front_xrb) {
Brian Paulc2901e42006-01-09 17:56:55 +0000877 xmesa_set_renderbuffer_funcs(front_xrb, xmesa->pixelformat,
878 xmesa->xm_visual->BitsPerPixel);
Brian Paulc2901e42006-01-09 17:56:55 +0000879 front_xrb->clearFunc = clear_pixmap;
Brian Paule4b23562005-05-04 20:11:35 +0000880 }
Brian Paulc2901e42006-01-09 17:56:55 +0000881
Brian Paulfaee3f02006-04-26 03:19:54 +0000882 back_xrb = xmbuf->backxrb;
Brian Paulc2901e42006-01-09 17:56:55 +0000883 if (back_xrb) {
Brian Paulc2901e42006-01-09 17:56:55 +0000884 xmesa_set_renderbuffer_funcs(back_xrb, xmesa->pixelformat,
885 xmesa->xm_visual->BitsPerPixel);
Brian Paulc2901e42006-01-09 17:56:55 +0000886 if (xmbuf->backxrb->pixmap) {
887 back_xrb->clearFunc = clear_pixmap;
888 }
889 else {
890 switch (xmesa->xm_visual->BitsPerPixel) {
891 case 8:
892 if (xmesa->xm_visual->hpcr_clear_flag) {
893 back_xrb->clearFunc = clear_HPCR_ximage;
894 }
895 else {
896 back_xrb->clearFunc = clear_8bit_ximage;
897 }
898 break;
899 case 16:
900 back_xrb->clearFunc = clear_16bit_ximage;
901 break;
902 case 24:
903 back_xrb->clearFunc = clear_24bit_ximage;
904 break;
905 case 32:
906 back_xrb->clearFunc = clear_32bit_ximage;
907 break;
908 default:
909 back_xrb->clearFunc = clear_nbit_ximage;
910 break;
Brian Paule4b23562005-05-04 20:11:35 +0000911 }
Brian Paulf9051452005-04-18 17:48:25 +0000912 }
Keith Whitwellec058582000-11-05 18:26:12 +0000913 }
Keith Whitwellec058582000-11-05 18:26:12 +0000914 }
915
Brian Paule4b23562005-05-04 20:11:35 +0000916 if (xmesa->xm_visual->hpcr_clear_flag) {
917 /* this depends on whether we're drawing to the front or back buffer */
918 /* XXX FIX THIS! */
919#if 0
920 if (pixmap) {
921 ctx->Driver.ClearColor = clear_color_HPCR_pixmap;
922 }
923 else {
924 ctx->Driver.ClearColor = clear_color_HPCR_ximage;
925 }
926#else
927 (void) clear_color_HPCR_pixmap;
928 (void) clear_color_HPCR_ximage;
929#endif
930 }
Keith Whitwellec058582000-11-05 18:26:12 +0000931}
932
933
934
Brian Paul738318b2003-04-04 17:17:50 +0000935/**
Daniel Borca3c9faa42004-10-12 07:32:11 +0000936 * In SW, we don't really compress GL_COMPRESSED_RGB[A] textures!
937 */
Brian Paul1f7c9142009-09-30 20:28:45 -0600938static gl_format
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400939choose_tex_format( struct gl_context *ctx, GLint internalFormat,
Daniel Borca3c9faa42004-10-12 07:32:11 +0000940 GLenum format, GLenum type )
941{
942 switch (internalFormat) {
943 case GL_COMPRESSED_RGB_ARB:
Brian Paul3fa7dbf2009-09-30 21:00:16 -0600944 return MESA_FORMAT_RGB888;
Daniel Borca3c9faa42004-10-12 07:32:11 +0000945 case GL_COMPRESSED_RGBA_ARB:
Brian Paul3fa7dbf2009-09-30 21:00:16 -0600946 return MESA_FORMAT_RGBA8888;
Daniel Borca3c9faa42004-10-12 07:32:11 +0000947 default:
948 return _mesa_choose_tex_format(ctx, internalFormat, format, type);
949 }
950}
951
952
953/**
Brian Paul65a66f52004-11-27 22:47:59 +0000954 * Called by glViewport.
955 * This is a good time for us to poll the current X window size and adjust
Brian Paule4b23562005-05-04 20:11:35 +0000956 * our renderbuffers to match the current window size.
957 * Remember, we have no opportunity to respond to conventional
958 * X Resize/StructureNotify events since the X driver has no event loop.
959 * Thus, we poll.
Brian Paul65a66f52004-11-27 22:47:59 +0000960 * Note that this trick isn't fool-proof. If the application never calls
961 * glViewport, our notion of the current window size may be incorrect.
Brian Paul444cd292006-04-27 02:47:50 +0000962 * That problem led to the GLX_MESA_resize_buffers extension.
Brian Paul65a66f52004-11-27 22:47:59 +0000963 */
964static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400965xmesa_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
Brian Paul65a66f52004-11-27 22:47:59 +0000966{
Brian Pauld21fa9c2006-10-14 22:52:17 +0000967 XMesaContext xmctx = XMESA_CONTEXT(ctx);
968 XMesaBuffer xmdrawbuf = XMESA_BUFFER(ctx->WinSysDrawBuffer);
969 XMesaBuffer xmreadbuf = XMESA_BUFFER(ctx->WinSysReadBuffer);
970 xmesa_check_and_update_buffer_size(xmctx, xmdrawbuf);
971 xmesa_check_and_update_buffer_size(xmctx, xmreadbuf);
Brian Paul444cd292006-04-27 02:47:50 +0000972 (void) x;
973 (void) y;
974 (void) w;
975 (void) h;
Brian Paul65a66f52004-11-27 22:47:59 +0000976}
977
978
Brian Paul4fb99502005-09-02 13:42:49 +0000979#if ENABLE_EXT_timer_query
980
981/*
982 * The GL_EXT_timer_query extension is not enabled for the XServer
983 * indirect renderer. Not sure about how/if wrapping of gettimeofday()
984 * is done, etc.
985 */
986
987struct xmesa_query_object
988{
989 struct gl_query_object Base;
990 struct timeval StartTime;
991};
992
993
994static struct gl_query_object *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400995xmesa_new_query_object(struct gl_context *ctx, GLuint id)
Brian Paul4fb99502005-09-02 13:42:49 +0000996{
997 struct xmesa_query_object *q = CALLOC_STRUCT(xmesa_query_object);
998 if (q) {
999 q->Base.Id = id;
1000 q->Base.Ready = GL_TRUE;
1001 }
1002 return &q->Base;
1003}
1004
1005
1006static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001007xmesa_begin_query(struct gl_context *ctx, struct gl_query_object *q)
Brian Paul4fb99502005-09-02 13:42:49 +00001008{
Keith Whitwell7ce59752008-09-20 06:34:23 -07001009 if (q->Target == GL_TIME_ELAPSED_EXT) {
Brian Paul4fb99502005-09-02 13:42:49 +00001010 struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
1011 (void) gettimeofday(&xq->StartTime, NULL);
1012 }
1013}
1014
1015
1016/**
1017 * Return the difference between the two given times in microseconds.
1018 */
Jouk Jansen21ed2952005-09-08 10:05:37 +00001019#ifdef __VMS
1020#define suseconds_t unsigned int
1021#endif
Brian Paul0fa8c592005-12-07 14:48:19 +00001022static GLuint64EXT
Brian Paul4fb99502005-09-02 13:42:49 +00001023time_diff(const struct timeval *t0, const struct timeval *t1)
1024{
Brian Paul0fa8c592005-12-07 14:48:19 +00001025 GLuint64EXT seconds0 = t0->tv_sec & 0xff; /* 0 .. 255 seconds */
1026 GLuint64EXT seconds1 = t1->tv_sec & 0xff; /* 0 .. 255 seconds */
1027 GLuint64EXT nanosec0 = (seconds0 * 1000000 + t0->tv_usec) * 1000;
1028 GLuint64EXT nanosec1 = (seconds1 * 1000000 + t1->tv_usec) * 1000;
1029 return nanosec1 - nanosec0;
Brian Paul4fb99502005-09-02 13:42:49 +00001030}
1031
1032
1033static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001034xmesa_end_query(struct gl_context *ctx, struct gl_query_object *q)
Brian Paul4fb99502005-09-02 13:42:49 +00001035{
Keith Whitwell7ce59752008-09-20 06:34:23 -07001036 if (q->Target == GL_TIME_ELAPSED_EXT) {
Brian Paul4fb99502005-09-02 13:42:49 +00001037 struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
1038 struct timeval endTime;
Brian Paul4fb99502005-09-02 13:42:49 +00001039 (void) gettimeofday(&endTime, NULL);
Brian Paul0fa8c592005-12-07 14:48:19 +00001040 /* result is in nanoseconds! */
1041 q->Result = time_diff(&xq->StartTime, &endTime);
Brian Paul4fb99502005-09-02 13:42:49 +00001042 }
1043 q->Ready = GL_TRUE;
1044}
1045
1046#endif /* ENABLE_timer_query */
1047
1048
Brian Paul65a66f52004-11-27 22:47:59 +00001049/**
Brian Pauld3fd7ba2004-01-20 02:49:27 +00001050 * Initialize the device driver function table with the functions
1051 * we implement in this driver.
Keith Whitwellec058582000-11-05 18:26:12 +00001052 */
Brian Paul29926a12004-11-27 21:20:37 +00001053void
1054xmesa_init_driver_functions( XMesaVisual xmvisual,
1055 struct dd_function_table *driver )
Keith Whitwellec058582000-11-05 18:26:12 +00001056{
Brian Pauld3fd7ba2004-01-20 02:49:27 +00001057 driver->GetString = get_string;
1058 driver->UpdateState = xmesa_update_state;
Brian Paul42b26f62006-10-17 17:51:39 +00001059 driver->GetBufferSize = NULL; /* OBSOLETE */
Brian Pauld3fd7ba2004-01-20 02:49:27 +00001060 driver->Flush = finish_or_flush;
1061 driver->Finish = finish_or_flush;
Brian Pauld3fd7ba2004-01-20 02:49:27 +00001062 driver->ClearColor = clear_color;
Brian Pauld3fd7ba2004-01-20 02:49:27 +00001063 driver->ColorMask = color_mask;
1064 driver->Enable = enable;
Brian Paul65a66f52004-11-27 22:47:59 +00001065 driver->Viewport = xmesa_viewport;
Brian Paul8126dfa2009-08-31 19:29:24 -06001066 if (TEST_META_FUNCS) {
Brian Paul4de8e212009-09-19 17:06:15 -06001067 driver->Clear = _mesa_meta_Clear;
1068 driver->CopyPixels = _mesa_meta_CopyPixels;
1069 driver->BlitFramebuffer = _mesa_meta_BlitFramebuffer;
1070 driver->DrawPixels = _mesa_meta_DrawPixels;
1071 driver->Bitmap = _mesa_meta_Bitmap;
Brian Paul8126dfa2009-08-31 19:29:24 -06001072 }
Brian Paulae5d7812009-08-31 21:14:50 -06001073 else {
1074 driver->Clear = clear_buffers;
Brian Paulae5d7812009-08-31 21:14:50 -06001075 driver->CopyPixels = xmesa_CopyPixels;
1076 if (xmvisual->undithered_pf == PF_8R8G8B &&
1077 xmvisual->dithered_pf == PF_8R8G8B &&
1078 xmvisual->BitsPerPixel == 32) {
1079 driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
1080 }
1081 else if (xmvisual->undithered_pf == PF_5R6G5B) {
1082 driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
1083 }
Brian Paul4fdc96d2009-09-03 21:19:23 -06001084 }
Brian Paul03a4f972010-11-24 12:01:02 -07001085
Brian Paul4fb99502005-09-02 13:42:49 +00001086#if ENABLE_EXT_texure_compression_s3tc
Daniel Borca3c9faa42004-10-12 07:32:11 +00001087 driver->ChooseTextureFormat = choose_tex_format;
Brian Paulbe2de8b2004-11-25 23:25:33 +00001088#else
1089 (void) choose_tex_format;
Daniel Borca3c9faa42004-10-12 07:32:11 +00001090#endif
Brian Paul4fb99502005-09-02 13:42:49 +00001091
1092#if ENABLE_EXT_timer_query
1093 driver->NewQueryObject = xmesa_new_query_object;
1094 driver->BeginQuery = xmesa_begin_query;
1095 driver->EndQuery = xmesa_end_query;
1096#endif
Brian Paul693f81b2000-09-07 15:40:30 +00001097}
Brian Paul097d2a02001-09-12 03:32:29 +00001098
1099
Brian Paul097d2a02001-09-12 03:32:29 +00001100#define XMESA_NEW_POINT (_NEW_POINT | \
1101 _NEW_RENDERMODE | \
1102 _SWRAST_NEW_RASTERMASK)
1103
1104#define XMESA_NEW_LINE (_NEW_LINE | \
1105 _NEW_TEXTURE | \
1106 _NEW_LIGHT | \
1107 _NEW_DEPTH | \
1108 _NEW_RENDERMODE | \
1109 _SWRAST_NEW_RASTERMASK)
1110
1111#define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
1112 _NEW_TEXTURE | \
1113 _NEW_LIGHT | \
1114 _NEW_DEPTH | \
1115 _NEW_RENDERMODE | \
1116 _SWRAST_NEW_RASTERMASK)
1117
1118
Brian Paul3a5bb172006-01-26 01:32:47 +00001119/**
1120 * Extend the software rasterizer with our line/point/triangle
Brian Paul097d2a02001-09-12 03:32:29 +00001121 * functions.
Brian Paul3a5bb172006-01-26 01:32:47 +00001122 * Called during context creation only.
Brian Paul097d2a02001-09-12 03:32:29 +00001123 */
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001124void xmesa_register_swrast_functions( struct gl_context *ctx )
Brian Paul097d2a02001-09-12 03:32:29 +00001125{
1126 SWcontext *swrast = SWRAST_CONTEXT( ctx );
1127
1128 swrast->choose_point = xmesa_choose_point;
1129 swrast->choose_line = xmesa_choose_line;
1130 swrast->choose_triangle = xmesa_choose_triangle;
1131
Brian Paul3a5bb172006-01-26 01:32:47 +00001132 /* XXX these lines have no net effect. Remove??? */
1133 swrast->InvalidatePointMask |= XMESA_NEW_POINT;
1134 swrast->InvalidateLineMask |= XMESA_NEW_LINE;
1135 swrast->InvalidateTriangleMask |= XMESA_NEW_TRIANGLE;
Brian Paul097d2a02001-09-12 03:32:29 +00001136}