Fix several conformance problems. Hack solution to line stipple problem.
[mesa.git] / src / mesa / drivers / glide / fxddspan.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 3.3
5 *
6 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
27 * terms stated above.
28 *
29 * Thank you for your contribution, David!
30 *
31 * Please make note of the above copyright/license statement. If you
32 * contributed code or bug fixes to this code under the previous (GNU
33 * Library) license and object to the new license, your code will be
34 * removed at your request. Please see the Mesa docs/COPYRIGHT file
35 * for more information.
36 *
37 * Additional Mesa/3Dfx driver developers:
38 * Daryll Strauss <daryll@precisioninsight.com>
39 * Keith Whitwell <keith@precisioninsight.com>
40 *
41 * See fxapi.h for more revision/author details.
42 */
43
44
45 /* fxdd.c - 3Dfx VooDoo Mesa span and pixel functions */
46
47
48 #ifdef HAVE_CONFIG_H
49 #include "conf.h"
50 #endif
51
52 #if defined(FX)
53
54 #include "fxdrv.h"
55
56 #ifdef _MSC_VER
57 #ifdef _WIN32
58 #pragma warning( disable : 4090 4022 )
59 /* 4101 : "different 'const' qualifier"
60 * 4022 : "pointer mistmatch for actual parameter 'n'
61 */
62 #endif
63 #endif
64
65
66 #if !defined(FXMESA_USE_ARGB)
67
68
69
70 #define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
71 FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
72
73
74
75 /* KW: Rearranged the args in the call to grLfbWriteRegion().
76 */
77 #define LFB_WRITE_SPAN_MESA(dst_buffer, \
78 dst_x, \
79 dst_y, \
80 src_width, \
81 src_stride, \
82 src_data) \
83 writeRegionClipped(fxMesa, dst_buffer, \
84 dst_x, \
85 dst_y, \
86 GR_LFB_SRC_FMT_8888, \
87 src_width, \
88 1, \
89 src_stride, \
90 src_data) \
91
92
93 #else /* !defined(FXMESA_USE_RGBA) */
94
95 #define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
96 FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
97
98
99 #define MESACOLOR_TO_ARGB(c) ( \
100 ( ((unsigned int)(c[ACOMP]))<<24 ) | \
101 ( ((unsigned int)(c[RCOMP]))<<16 ) | \
102 ( ((unsigned int)(c[GCOMP]))<<8 ) | \
103 ( (unsigned int)(c[BCOMP])) )
104
105 inline void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer,
106 FxU32 dst_x,
107 FxU32 dst_y,
108 FxU32 src_width,
109 FxI32 src_stride,
110 void *src_data )
111 {
112 /* Covert to ARGB */
113 GLubyte (*rgba)[4] = src_data;
114 GLuint argb[MAX_WIDTH];
115 int i;
116
117 for (i = 0; i < src_width; i++)
118 {
119 argb[i] = MESACOLOR_TO_ARGB(rgba[i]);
120 }
121 writeRegionClipped( /*fxMesa,*/ NULL, dst_buffer,
122 dst_x,
123 dst_y,
124 GR_LFB_SRC_FMT_8888,
125 src_width,
126 1,
127 src_stride,
128 (void*)argb);
129 }
130
131 #endif /* !defined(FXMESA_USE_RGBA) */
132
133
134 /************************************************************************/
135 /***** Span functions *****/
136 /************************************************************************/
137
138
139 static void fxDDWriteRGBASpan(const GLcontext *ctx,
140 GLuint n, GLint x, GLint y,
141 const GLubyte rgba[][4], const GLubyte mask[])
142 {
143 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
144 GLuint i;
145 GLint bottom=fxMesa->height-1;
146
147 if (MESA_VERBOSE&VERBOSE_DRIVER) {
148 fprintf(stderr,"fxmesa: fxDDWriteRGBASpan(...)\n");
149 }
150
151 if (mask) {
152 int span=0;
153
154 for (i=0;i<n;i++) {
155 if (mask[i]) {
156 ++span;
157 } else {
158 if (span > 0) {
159 LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y,
160 /* GR_LFB_SRC_FMT_8888,*/ span, /*1,*/ 0, (void *) rgba[i-span] );
161 span = 0;
162 }
163 }
164 }
165
166 if (span > 0)
167 LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y,
168 /* GR_LFB_SRC_FMT_8888, */ span, /*1,*/ 0, (void *) rgba[n-span] );
169 } else
170 LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/
171 n,/* 1,*/ 0, (void *) rgba );
172 }
173
174
175 static void fxDDWriteRGBSpan(const GLcontext *ctx,
176 GLuint n, GLint x, GLint y,
177 const GLubyte rgb[][3], const GLubyte mask[])
178 {
179 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
180 GLuint i;
181 GLint bottom=fxMesa->height-1;
182 GLubyte rgba[MAX_WIDTH][4];
183
184 if (MESA_VERBOSE&VERBOSE_DRIVER) {
185 fprintf(stderr,"fxmesa: fxDDWriteRGBSpan()\n");
186 }
187
188 if (mask) {
189 int span=0;
190
191 for (i=0;i<n;i++) {
192 if (mask[i]) {
193 rgba[span][RCOMP] = rgb[i][0];
194 rgba[span][GCOMP] = rgb[i][1];
195 rgba[span][BCOMP] = rgb[i][2];
196 rgba[span][ACOMP] = 255;
197 ++span;
198 } else {
199 if (span > 0) {
200 LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y,
201 /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba );
202 span = 0;
203 }
204 }
205 }
206
207 if (span > 0)
208 LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y,
209 /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba );
210 } else {
211 for (i=0;i<n;i++) {
212 rgba[i][RCOMP]=rgb[i][0];
213 rgba[i][GCOMP]=rgb[i][1];
214 rgba[i][BCOMP]=rgb[i][2];
215 rgba[i][ACOMP]=255;
216 }
217
218 LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/
219 n,/* 1,*/ 0, (void *) rgba );
220 }
221 }
222
223
224 static void fxDDWriteMonoRGBASpan(const GLcontext *ctx,
225 GLuint n, GLint x, GLint y,
226 const GLchan color[4], const GLubyte mask[])
227 {
228 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
229 GLuint i;
230 GLint bottom=fxMesa->height-1;
231 GLuint data[MAX_WIDTH];
232 GrColor_t gColor = FXCOLOR4(color);
233
234 if (MESA_VERBOSE&VERBOSE_DRIVER) {
235 fprintf(stderr,"fxmesa: fxDDWriteMonoRGBASpan(...)\n");
236 }
237
238 if (mask) {
239 int span=0;
240
241 for (i=0;i<n;i++) {
242 if (mask[i]) {
243 data[span] = (GLuint) gColor;
244 ++span;
245 } else {
246 if (span > 0) {
247 writeRegionClipped(fxMesa, fxMesa->currentFB, x+i-span, bottom-y,
248 GR_LFB_SRC_FMT_8888, span, 1, 0,
249 (void *) data );
250 span = 0;
251 }
252 }
253 }
254
255 if (span > 0)
256 writeRegionClipped(fxMesa, fxMesa->currentFB, x+n-span, bottom-y,
257 GR_LFB_SRC_FMT_8888, span, 1, 0,
258 (void *) data );
259 } else {
260 for (i=0;i<n;i++) {
261 data[i]=(GLuint) gColor;
262 }
263
264 writeRegionClipped(fxMesa, fxMesa->currentFB, x, bottom-y, GR_LFB_SRC_FMT_8888,
265 n, 1, 0, (void *) data );
266 }
267 }
268
269
270 #if 0
271 static void fxDDReadRGBASpan(const GLcontext *ctx,
272 GLuint n, GLint x, GLint y, GLubyte rgba[][4])
273 {
274 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
275 GLushort data[MAX_WIDTH];
276 GLuint i;
277 GLint bottom=fxMesa->height-1;
278
279 printf("read span %d, %d, %d\n", x,y,n);
280 if (MESA_VERBOSE&VERBOSE_DRIVER) {
281 fprintf(stderr,"fxmesa: fxDDReadRGBASpan(...)\n");
282 }
283
284 assert(n < MAX_WIDTH);
285
286 FX_grLfbReadRegion( fxMesa->currentFB, x, bottom-y, n, 1, 0, data);
287
288 for (i=0;i<n;i++) {
289 GLushort pixel = data[i];
290 rgba[i][RCOMP] = FX_PixelToR[pixel];
291 rgba[i][GCOMP] = FX_PixelToG[pixel];
292 rgba[i][BCOMP] = FX_PixelToB[pixel];
293 rgba[i][ACOMP] = 255;
294 }
295 }
296 #endif
297
298
299 /*
300 * Read a span of 16-bit RGB pixels. Note, we don't worry about cliprects
301 * since OpenGL says obscured pixels have undefined values.
302 */
303 static void read_R5G6B5_span(const GLcontext *ctx,
304 GLuint n, GLint x, GLint y, GLubyte rgba[][4])
305 {
306 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
307 GrLfbInfo_t info;
308 BEGIN_BOARD_LOCK();
309 if (grLfbLock(GR_LFB_READ_ONLY,
310 fxMesa->currentFB,
311 GR_LFBWRITEMODE_ANY,
312 GR_ORIGIN_UPPER_LEFT,
313 FXFALSE,
314 &info)) {
315 const GLint winX = 0;
316 const GLint winY = fxMesa->height - 1;
317 const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
318 const GLushort *data16 = (const GLushort *) info.lfbPtr
319 + (winY - y) * srcStride
320 + (winX + x);
321 const GLuint *data32 = (const GLuint *) data16;
322 GLuint i, j;
323 GLuint extraPixel = (n & 1);
324 n -= extraPixel;
325 for (i = j = 0; i < n; i += 2, j++) {
326 GLuint pixel = data32[j];
327 GLuint pixel0 = pixel & 0xffff;
328 GLuint pixel1 = pixel >> 16;
329 rgba[i][RCOMP] = FX_PixelToR[pixel0];
330 rgba[i][GCOMP] = FX_PixelToG[pixel0];
331 rgba[i][BCOMP] = FX_PixelToB[pixel0];
332 rgba[i][ACOMP] = 255;
333 rgba[i+1][RCOMP] = FX_PixelToR[pixel1];
334 rgba[i+1][GCOMP] = FX_PixelToG[pixel1];
335 rgba[i+1][BCOMP] = FX_PixelToB[pixel1];
336 rgba[i+1][ACOMP] = 255;
337 }
338 if (extraPixel) {
339 GLushort pixel = data16[n];
340 rgba[n][RCOMP] = FX_PixelToR[pixel];
341 rgba[n][GCOMP] = FX_PixelToG[pixel];
342 rgba[n][BCOMP] = FX_PixelToB[pixel];
343 rgba[n][ACOMP] = 255;
344 }
345
346 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
347 }
348 END_BOARD_LOCK();
349 }
350
351
352 /************************************************************************/
353 /***** Pixel functions *****/
354 /************************************************************************/
355
356 static void fxDDWriteRGBAPixels(const GLcontext *ctx,
357 GLuint n, const GLint x[], const GLint y[],
358 CONST GLubyte rgba[][4], const GLubyte mask[])
359 {
360 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
361 GLuint i;
362 GLint bottom=fxMesa->height-1;
363
364 if (MESA_VERBOSE&VERBOSE_DRIVER) {
365 fprintf(stderr,"fxmesa: fxDDWriteRGBAPixels(...)\n");
366 }
367
368 for(i=0;i<n;i++)
369 if(mask[i])
370 LFB_WRITE_SPAN_MESA(fxMesa->currentFB, x[i], bottom-y[i],
371 1, 1, (void *)rgba[i]);
372 }
373
374 static void fxDDWriteMonoRGBAPixels(const GLcontext *ctx,
375 GLuint n, const GLint x[], const GLint y[],
376 const GLchan color[4], const GLubyte mask[])
377 {
378 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
379 GLuint i;
380 GLint bottom=fxMesa->height-1;
381 GrColor_t gColor = FXCOLOR4(color);
382
383 if (MESA_VERBOSE&VERBOSE_DRIVER) {
384 fprintf(stderr,"fxmesa: fxDDWriteMonoRGBAPixels(...)\n");
385 }
386
387 for(i=0;i<n;i++)
388 if(mask[i])
389 writeRegionClipped(fxMesa, fxMesa->currentFB,x[i],bottom-y[i],
390 GR_LFB_SRC_FMT_8888,1,1,0,(void *) &gColor);
391 }
392
393
394 static void read_R5G6B5_pixels(const GLcontext *ctx,
395 GLuint n, const GLint x[], const GLint y[],
396 GLubyte rgba[][4], const GLubyte mask[])
397 {
398 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
399 GrLfbInfo_t info;
400 BEGIN_BOARD_LOCK();
401 if (grLfbLock(GR_LFB_READ_ONLY,
402 fxMesa->currentFB,
403 GR_LFBWRITEMODE_ANY,
404 GR_ORIGIN_UPPER_LEFT,
405 FXFALSE,
406 &info)) {
407 const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
408 const GLint winX = 0;
409 const GLint winY = fxMesa->height - 1;
410 GLuint i;
411 for(i=0;i<n;i++) {
412 if(mask[i]) {
413 const GLushort *data16 = (const GLushort *) info.lfbPtr
414 + (winY - y[i]) * srcStride
415 + (winX + x[i]);
416 const GLushort pixel = *data16;
417 rgba[i][RCOMP] = FX_PixelToR[pixel];
418 rgba[i][GCOMP] = FX_PixelToG[pixel];
419 rgba[i][BCOMP] = FX_PixelToB[pixel];
420 rgba[i][ACOMP] = 255;
421 }
422 }
423 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
424 }
425 END_BOARD_LOCK();
426 }
427
428
429
430 /************************************************************************/
431 /***** Depth functions *****/
432 /************************************************************************/
433
434 void fxDDWriteDepthSpan(GLcontext *ctx,
435 GLuint n, GLint x, GLint y, const GLdepth depth[],
436 const GLubyte mask[])
437 {
438 fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
439 GLint bottom = fxMesa->height - 1;
440
441 if (MESA_VERBOSE & VERBOSE_DRIVER) {
442 fprintf(stderr, "fxmesa: fxDDWriteDepthSpan(...)\n");
443 }
444
445
446 if (mask) {
447 GLint i;
448 for (i = 0; i < n; i++) {
449 if (mask[i]) {
450 GLshort d = depth[i];
451 writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x + i, bottom - y,
452 GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &d);
453 }
454 }
455 }
456 else {
457 GLushort depth16[MAX_WIDTH];
458 GLint i;
459 for (i = 0; i < n; i++) {
460 depth16[i] = depth[i];
461 }
462 writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x, bottom - y,
463 GR_LFB_SRC_FMT_ZA16, n, 1, 0, (void *) depth16);
464 }
465 }
466
467
468 void fxDDReadDepthSpan(GLcontext *ctx,
469 GLuint n, GLint x, GLint y, GLdepth depth[])
470 {
471 fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
472 GLint bottom = fxMesa->height - 1;
473 GLushort depth16[MAX_WIDTH];
474 GLuint i;
475
476 if (MESA_VERBOSE & VERBOSE_DRIVER) {
477 fprintf(stderr, "fxmesa: fxDDReadDepthSpan(...)\n");
478 }
479
480 FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER, x, bottom - y, n, 1, 0, depth16);
481 for (i = 0; i < n; i++) {
482 depth[i] = depth16[i];
483 }
484 }
485
486
487
488 void fxDDWriteDepthPixels(GLcontext *ctx,
489 GLuint n, const GLint x[], const GLint y[],
490 const GLdepth depth[], const GLubyte mask[])
491 {
492 fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
493 GLint bottom = fxMesa->height - 1;
494 GLuint i;
495
496 if (MESA_VERBOSE & VERBOSE_DRIVER) {
497 fprintf(stderr, "fxmesa: fxDDWriteDepthPixels(...)\n");
498 }
499
500 for (i = 0; i < n; i++) {
501 if (mask[i]) {
502 int xpos = x[i];
503 int ypos = bottom - y[i];
504 GLushort d = depth[i];
505 writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, xpos, ypos,
506 GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &d);
507 }
508 }
509 }
510
511
512 void fxDDReadDepthPixels(GLcontext *ctx, GLuint n,
513 const GLint x[], const GLint y[], GLdepth depth[])
514 {
515 fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
516 GLint bottom = fxMesa->height - 1;
517 GLuint i;
518
519 if (MESA_VERBOSE & VERBOSE_DRIVER) {
520 fprintf(stderr, "fxmesa: fxDDReadDepthPixels(...)\n");
521 }
522
523 for (i = 0; i < n; i++) {
524 int xpos = x[i];
525 int ypos = bottom - y[i];
526 GLushort d;
527 FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER, xpos, ypos, 1, 1, 0, &d);
528 depth[i] = d;
529 }
530 }
531
532
533
534
535 /************************************************************************/
536
537
538 void fxSetupDDSpanPointers(GLcontext *ctx)
539 {
540 ctx->Driver.WriteRGBASpan =fxDDWriteRGBASpan;
541 ctx->Driver.WriteRGBSpan =fxDDWriteRGBSpan;
542 ctx->Driver.WriteMonoRGBASpan =fxDDWriteMonoRGBASpan;
543 ctx->Driver.WriteRGBAPixels =fxDDWriteRGBAPixels;
544 ctx->Driver.WriteMonoRGBAPixels =fxDDWriteMonoRGBAPixels;
545
546 ctx->Driver.WriteCI8Span =NULL;
547 ctx->Driver.WriteCI32Span =NULL;
548 ctx->Driver.WriteMonoCISpan =NULL;
549 ctx->Driver.WriteCI32Pixels =NULL;
550 ctx->Driver.WriteMonoCIPixels =NULL;
551
552 /* ctx->Driver.ReadRGBASpan =fxDDReadRGBASpan;*/
553 ctx->Driver.ReadRGBASpan = read_R5G6B5_span;
554 ctx->Driver.ReadRGBAPixels = read_R5G6B5_pixels;
555
556 ctx->Driver.ReadCI32Span =NULL;
557 ctx->Driver.ReadCI32Pixels =NULL;
558 }
559
560
561 #else
562
563
564 /*
565 * Need this to provide at least one external definition.
566 */
567
568 extern int gl_fx_dummy_function_span(void);
569 int gl_fx_dummy_function_span(void)
570 {
571 return 0;
572 }
573
574 #endif /* FX */