enable feedback rendering
[mesa.git] / src / mesa / drivers / dri / tdfx / tdfx_span.c
1 /* -*- mode: c; c-basic-offset: 3 -*-
2 *
3 * Copyright 2000 VA Linux Systems Inc., Fremont, California.
4 *
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26 /* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_span.c,v 1.7 2002/10/30 12:52:00 alanh Exp $ */
27
28 /*
29 * Original rewrite:
30 * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
31 *
32 * Authors:
33 * Gareth Hughes <gareth@valinux.com>
34 * Brian Paul <brianp@valinux.com>
35 * Keith Whitwell <keith@tungstengraphics.com>
36 *
37 */
38
39 #include "tdfx_context.h"
40 #include "tdfx_lock.h"
41 #include "tdfx_span.h"
42 #include "tdfx_render.h"
43 #include "swrast/swrast.h"
44
45
46 #define DBG 0
47
48
49 #define LOCAL_VARS \
50 __DRIdrawablePrivate *dPriv = fxMesa->driDrawable; \
51 tdfxScreenPrivate *fxPriv = fxMesa->fxScreen; \
52 GLboolean isFront = (ctx->DrawBuffer->_ColorDrawBufferMask[0] \
53 == BUFFER_BIT_FRONT_LEFT); \
54 GLuint pitch = isFront ? (fxMesa->screen_width * BYTESPERPIXEL) \
55 : info.strideInBytes; \
56 GLuint height = fxMesa->height; \
57 char *buf = (char *)((char *)info.lfbPtr + \
58 dPriv->x * fxPriv->cpp + \
59 dPriv->y * pitch); \
60 GLuint p; \
61 (void) buf; (void) p;
62
63
64 #define Y_FLIP(_y) (height - _y - 1)
65
66
67 #define HW_WRITE_LOCK() \
68 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); \
69 GrLfbInfo_t info; \
70 FLUSH_BATCH( fxMesa ); \
71 UNLOCK_HARDWARE( fxMesa ); \
72 LOCK_HARDWARE( fxMesa ); \
73 info.size = sizeof(GrLfbInfo_t); \
74 if ( fxMesa->Glide.grLfbLock( GR_LFB_WRITE_ONLY, \
75 fxMesa->DrawBuffer, LFB_MODE, \
76 GR_ORIGIN_UPPER_LEFT, FXFALSE, &info ) ) \
77 {
78
79 #define HW_WRITE_UNLOCK() \
80 fxMesa->Glide.grLfbUnlock( GR_LFB_WRITE_ONLY, fxMesa->DrawBuffer );\
81 }
82
83
84 #define HW_READ_LOCK() \
85 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); \
86 GrLfbInfo_t info; \
87 FLUSH_BATCH( fxMesa ); \
88 UNLOCK_HARDWARE( fxMesa ); \
89 LOCK_HARDWARE( fxMesa ); \
90 info.size = sizeof(GrLfbInfo_t); \
91 if ( fxMesa->Glide.grLfbLock( GR_LFB_READ_ONLY, fxMesa->ReadBuffer, \
92 LFB_MODE, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info ) ) \
93 {
94
95 #define HW_READ_UNLOCK() \
96 fxMesa->Glide.grLfbUnlock( GR_LFB_READ_ONLY, fxMesa->ReadBuffer );\
97 }
98
99
100 #define HW_WRITE_CLIPLOOP() \
101 do { \
102 int _nc = fxMesa->numClipRects; \
103 while (_nc--) { \
104 int minx = fxMesa->pClipRects[_nc].x1 - fxMesa->x_offset; \
105 int miny = fxMesa->pClipRects[_nc].y1 - fxMesa->y_offset; \
106 int maxx = fxMesa->pClipRects[_nc].x2 - fxMesa->x_offset; \
107 int maxy = fxMesa->pClipRects[_nc].y2 - fxMesa->y_offset;
108
109 #define HW_READ_CLIPLOOP() \
110 do { \
111 const __DRIdrawablePrivate *dPriv = fxMesa->driDrawable; \
112 drm_clip_rect_t *rect = dPriv->pClipRects; \
113 int _nc = dPriv->numClipRects; \
114 while (_nc--) { \
115 const int minx = rect->x1 - fxMesa->x_offset; \
116 const int miny = rect->y1 - fxMesa->y_offset; \
117 const int maxx = rect->x2 - fxMesa->x_offset; \
118 const int maxy = rect->y2 - fxMesa->y_offset; \
119 rect++;
120
121 #define HW_ENDCLIPLOOP() \
122 } \
123 } while (0)
124
125
126
127 #define LFB_MODE GR_LFBWRITEMODE_565
128
129
130 /* 16 bit, RGB565 color spanline and pixel functions */ \
131
132 #undef INIT_MONO_PIXEL
133 #define INIT_MONO_PIXEL(p, color) \
134 p = TDFXPACKCOLOR565( color[0], color[1], color[2] )
135
136
137 #define WRITE_RGBA( _x, _y, r, g, b, a ) \
138 *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \
139 (((int)g & 0xfc) << 3) | \
140 (((int)b & 0xf8) >> 3))
141
142 #define WRITE_PIXEL( _x, _y, p ) \
143 *(GLushort *)(buf + _x*2 + _y*pitch) = p
144
145 #define READ_RGBA( rgba, _x, _y ) \
146 do { \
147 GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \
148 rgba[0] = (((p >> 11) & 0x1f) * 255) / 31; \
149 rgba[1] = (((p >> 5) & 0x3f) * 255) / 63; \
150 rgba[2] = (((p >> 0) & 0x1f) * 255) / 31; \
151 rgba[3] = 0xff; \
152 } while (0)
153
154 #define TAG(x) tdfx##x##_RGB565
155 #define BYTESPERPIXEL 2
156 #include "spantmp.h"
157 #undef BYTESPERPIXEL
158
159
160 /* 16 bit, BGR565 color spanline and pixel functions */ \
161 #if 0
162
163 #define WRITE_RGBA( _x, _y, r, g, b, a ) \
164 *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)b & 0xf8) << 8) | \
165 (((int)g & 0xfc) << 3) | \
166 (((int)r & 0xf8) >> 3))
167
168 #define WRITE_PIXEL( _x, _y, p ) \
169 *(GLushort *)(buf + _x*2 + _y*pitch) = p
170
171 #define READ_RGBA( rgba, _x, _y ) \
172 do { \
173 GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \
174 rgba[0] = (p << 3) & 0xf8; \
175 rgba[1] = (p >> 3) & 0xfc; \
176 rgba[2] = (p >> 8) & 0xf8; \
177 rgba[3] = 0xff; \
178 } while (0)
179
180 #define TAG(x) tdfx##x##_BGR565
181 #define BYTESPERPIXEL 2
182 #include "spantmp.h"
183 #undef BYTESPERPIXEL
184 #endif
185
186
187 #undef LFB_MODE
188 #define LFB_MODE GR_LFBWRITEMODE_888
189
190
191 /* 24 bit, RGB888 color spanline and pixel functions */
192 #undef INIT_MONO_PIXEL
193 #define INIT_MONO_PIXEL(p, color) \
194 p = TDFXPACKCOLOR888( color[0], color[1], color[2] )
195
196 #define WRITE_RGBA( _x, _y, r, g, b, a ) \
197 *(GLuint *)(buf + _x*3 + _y*pitch) = ((b << 0) | \
198 (g << 8) | \
199 (r << 16))
200
201 #define WRITE_PIXEL( _x, _y, p ) \
202 *(GLuint *)(buf + _x*3 + _y*pitch) = p
203
204 #define READ_RGBA( rgba, _x, _y ) \
205 do { \
206 GLuint p = *(GLuint *)(buf + _x*3 + _y*pitch); \
207 rgba[0] = (p >> 16) & 0xff; \
208 rgba[1] = (p >> 8) & 0xff; \
209 rgba[2] = (p >> 0) & 0xff; \
210 rgba[3] = 0xff; \
211 } while (0)
212
213 #define TAG(x) tdfx##x##_RGB888
214 #define BYTESPERPIXEL 4
215 #include "spantmp.h"
216 #undef BYTESPERPIXEL
217
218
219 #undef LFB_MODE
220 #define LFB_MODE GR_LFBWRITEMODE_8888
221
222
223 /* 32 bit, ARGB8888 color spanline and pixel functions */
224 #undef INIT_MONO_PIXEL
225 #define INIT_MONO_PIXEL(p, color) \
226 p = TDFXPACKCOLOR8888( color[0], color[1], color[2], color[3] )
227
228 #define WRITE_RGBA( _x, _y, r, g, b, a ) \
229 *(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \
230 (g << 8) | \
231 (r << 16) | \
232 (a << 24) )
233
234 #define WRITE_PIXEL( _x, _y, p ) \
235 *(GLuint *)(buf + _x*4 + _y*pitch) = p
236
237 #define READ_RGBA( rgba, _x, _y ) \
238 do { \
239 GLuint p = *(GLuint *)(buf + _x*4 + _y*pitch); \
240 rgba[0] = (p >> 16) & 0xff; \
241 rgba[1] = (p >> 8) & 0xff; \
242 rgba[2] = (p >> 0) & 0xff; \
243 rgba[3] = (p >> 24) & 0xff; \
244 } while (0)
245
246 #define TAG(x) tdfx##x##_ARGB8888
247 #define BYTESPERPIXEL 4
248 #include "spantmp.h"
249 #undef BYTESPERPIXEL
250
251
252
253 /* ================================================================
254 * Old span functions below...
255 */
256
257
258 /*
259 * Examine the cliprects to generate an array of flags to indicate
260 * which pixels in a span are visible. Note: (x,y) is a screen
261 * coordinate.
262 */
263 static void
264 generate_vismask(const tdfxContextPtr fxMesa, GLint x, GLint y, GLint n,
265 GLubyte vismask[])
266 {
267 GLboolean initialized = GL_FALSE;
268 GLint i, j;
269
270 /* Ensure we clear the visual mask */
271 MEMSET(vismask, 0, n);
272
273 /* turn on flags for all visible pixels */
274 for (i = 0; i < fxMesa->numClipRects; i++) {
275 const drm_clip_rect_t *rect = &fxMesa->pClipRects[i];
276
277 if (y >= rect->y1 && y < rect->y2) {
278 if (x >= rect->x1 && x + n <= rect->x2) {
279 /* common case, whole span inside cliprect */
280 MEMSET(vismask, 1, n);
281 return;
282 }
283 if (x < rect->x2 && x + n >= rect->x1) {
284 /* some of the span is inside the rect */
285 GLint start, end;
286 if (!initialized) {
287 MEMSET(vismask, 0, n);
288 initialized = GL_TRUE;
289 }
290 if (x < rect->x1)
291 start = rect->x1 - x;
292 else
293 start = 0;
294 if (x + n > rect->x2)
295 end = rect->x2 - x;
296 else
297 end = n;
298 assert(start >= 0);
299 assert(end <= n);
300 for (j = start; j < end; j++)
301 vismask[j] = 1;
302 }
303 }
304 }
305 }
306
307 /*
308 * Examine cliprects and determine if the given screen pixel is visible.
309 */
310 static GLboolean
311 visible_pixel(const tdfxContextPtr fxMesa, int scrX, int scrY)
312 {
313 int i;
314 for (i = 0; i < fxMesa->numClipRects; i++) {
315 const drm_clip_rect_t *rect = &fxMesa->pClipRects[i];
316 if (scrX >= rect->x1 &&
317 scrX < rect->x2 &&
318 scrY >= rect->y1 && scrY < rect->y2) return GL_TRUE;
319 }
320 return GL_FALSE;
321 }
322
323
324
325 /*
326 * Depth buffer read/write functions.
327 */
328 /*
329 * To read the frame buffer, we need to lock and unlock it. The
330 * four macros {READ,WRITE}_FB_SPAN_{LOCK,UNLOCK}
331 * do this for us.
332 *
333 * Note that the lock must be matched with an unlock. These
334 * macros include a spare curly brace, so they must
335 * be syntactically matched.
336 *
337 * Note, also, that you can't lock a buffer twice with different
338 * modes. That is to say, you can't lock a buffer in both read
339 * and write modes. The strideInBytes and LFB pointer will be
340 * the same with read and write locks, so you can use either.
341 * o The HW has different state for reads and writes, so
342 * locking it twice may give screwy results.
343 * o The DRM won't let you lock twice. It hangs. This is probably
344 * because of the LOCK_HARDWARE IN THE *_FB_SPAN_LOCK macros,
345 * and could be eliminated with nonlocking lock routines. But
346 * what's the point after all.
347 */
348 #define READ_FB_SPAN_LOCK(fxMesa, info, target_buffer) \
349 UNLOCK_HARDWARE(fxMesa); \
350 LOCK_HARDWARE(fxMesa); \
351 (info).size=sizeof(info); \
352 if (fxMesa->Glide.grLfbLock(GR_LFB_READ_ONLY, \
353 target_buffer, \
354 GR_LFBWRITEMODE_ANY, \
355 GR_ORIGIN_UPPER_LEFT, \
356 FXFALSE, \
357 &(info))) {
358
359 #define READ_FB_SPAN_UNLOCK(fxMesa, target_buffer) \
360 fxMesa->Glide.grLfbUnlock(GR_LFB_READ_ONLY, target_buffer); \
361 } else { \
362 fprintf(stderr, "tdfxDriver: Can't get %s (%d) read lock\n", \
363 (target_buffer == GR_BUFFER_BACKBUFFER) \
364 ? "back buffer" \
365 : ((target_buffer == GR_BUFFER_AUXBUFFER) \
366 ? "depth buffer" \
367 : "unknown buffer"), \
368 target_buffer); \
369 }
370
371 #define WRITE_FB_SPAN_LOCK(fxMesa, info, target_buffer, write_mode) \
372 UNLOCK_HARDWARE(fxMesa); \
373 LOCK_HARDWARE(fxMesa); \
374 info.size=sizeof(info); \
375 if (fxMesa->Glide.grLfbLock(GR_LFB_WRITE_ONLY, \
376 target_buffer, \
377 write_mode, \
378 GR_ORIGIN_UPPER_LEFT, \
379 FXFALSE, \
380 &info)) {
381
382 #define WRITE_FB_SPAN_UNLOCK(fxMesa, target_buffer) \
383 fxMesa->Glide.grLfbUnlock(GR_LFB_WRITE_ONLY, target_buffer); \
384 } else { \
385 fprintf(stderr, "tdfxDriver: Can't get %s (%d) write lock\n", \
386 (target_buffer == GR_BUFFER_BACKBUFFER) \
387 ? "back buffer" \
388 : ((target_buffer == GR_BUFFER_AUXBUFFER) \
389 ? "depth buffer" \
390 : "unknown buffer"), \
391 target_buffer); \
392 }
393
394 /*
395 * Because the Linear Frame Buffer is not necessarily aligned
396 * with the depth buffer, we have to do some fiddling
397 * around to get the right addresses.
398 *
399 * Perhaps a picture is in order. The Linear Frame Buffer
400 * looks like this:
401 *
402 * |<----------------------info.strideInBytes------------->|
403 * |<-----physicalStrideInBytes------->|
404 * +-----------------------------------+xxxxxxxxxxxxxxxxxxx+
405 * | | |
406 * | Legal Memory | Forbidden Zone |
407 * | | |
408 * +-----------------------------------+xxxxxxxxxxxxxxxxxxx+
409 *
410 * You can only reliably read and write legal locations. Reads
411 * and writes from the Forbidden Zone will return undefined values,
412 * and may cause segmentation faults.
413 *
414 * Now, the depth buffer may not end up in a location such each
415 * scan line is an LFB line. For example, the depth buffer may
416 * look like this:
417 *
418 * wrapped ordinary.
419 * +-----------------------------------+xxxxxxxxxxxxxxxxxxx+
420 * |0000000000000000000000 | | back
421 * |1111111111111111111111 | | buffer
422 * |2222222222222222222222 | |
423 * |4096b align. padxx00000000000000000| Forbidden Zone | depth
424 * |0000 11111111111111111| | buffer
425 * |1111 22222222222222222| |
426 * |2222 | |
427 * +-----------------------------------+xxxxxxxxxxxxxxxxxxx+
428 * where each number is the scan line number. We know it will
429 * be aligned on 128 byte boundaries, at least. Aligning this
430 * on a scanline boundary causes the back and depth buffers to
431 * thrash in the SST1 cache. (Note that the back buffer is always
432 * allocated at the beginning of LFB memory, and so it is always
433 * properly aligned with the LFB stride.)
434 *
435 * We call the beginning of the line (which is the rightmost
436 * part of the depth line in the picture above) the *ordinary* part
437 * of the scanline, and the end of the line (which is the
438 * leftmost part, one line below) the *wrapped* part of the scanline.
439 * a.) We need to know what x value to subtract from the screen
440 * x coordinate to index into the wrapped part.
441 * b.) We also need to figure out if we need to read from the ordinary
442 * part scan line, or from the wrapped part of the scan line.
443 *
444 * [ad a]
445 * The first wrapped x coordinate is that coordinate such that
446 * depthBufferOffset&(info.strideInBytes) + x*elmentSize {*}
447 * > physicalStrideInBytes
448 * where depthBufferOffset is the LFB distance in bytes
449 * from the back buffer to the depth buffer. The expression
450 * depthBufferOffset&(info.strideInBytes)
451 * is then the offset (in bytes) from the beginining of (any)
452 * depth buffer line to first element in the line.
453 * Simplifying inequation {*} above we see that x is the smallest
454 * value such that
455 * x*elementSize > physicalStrideInBytes {**}
456 * - depthBufferOffset&(info.strideInBytes)
457 * Now, we know that both the summands on the right are multiples of
458 * 128, and elementSize <= 4, so if equality holds in {**}, x would
459 * be a multiple of 32. Thus we can set x to
460 * xwrapped = (physicalStrideInBytes
461 * - depthBufferOffset&(info.strideInBytes))/elementSize
462 * + 1
463 *
464 * [ad b]
465 * Question b is now simple. We read from the wrapped scan line if
466 * x is greater than xwrapped.
467 */
468 #define TILE_WIDTH_IN_BYTES 128
469 #define TILE_WIDTH_IN_ZOXELS(bpz) (TILE_WIDTH_IN_BYTES/(bpz))
470 #define TILE_HEIGHT_IN_LINES 32
471 typedef struct
472 {
473 void *lfbPtr;
474 void *lfbWrapPtr;
475 FxU32 LFBStrideInElts;
476 GLint firstWrappedX;
477 }
478 LFBParameters;
479
480 /*
481 * We need information about the back buffer. Note that
482 * this function *cannot be called* while the aux buffer
483 * is locked, or the caller will hang.
484 *
485 * Only Glide knows the LFB address of the back and depth
486 * offsets. The upper levels of Mesa know the depth offset,
487 * but that is not in LFB space, it is tiled memory space,
488 * and is not useable for us.
489 */
490 static void
491 GetBackBufferInfo(tdfxContextPtr fxMesa, GrLfbInfo_t * backBufferInfo)
492 {
493 READ_FB_SPAN_LOCK(fxMesa, *backBufferInfo, GR_BUFFER_BACKBUFFER);
494 READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_BACKBUFFER);
495 }
496
497 static void
498 GetFbParams(tdfxContextPtr fxMesa,
499 GrLfbInfo_t * info,
500 GrLfbInfo_t * backBufferInfo,
501 LFBParameters * ReadParamsp, FxU32 elementSize)
502 {
503 FxU32 physicalStrideInBytes, bufferOffset;
504 FxU32 strideInBytes = info->strideInBytes;
505 char *lfbPtr = (char *) (info->lfbPtr); /* For arithmetic, use char * */
506
507 /*
508 * These two come directly from the info structure.
509 */
510 ReadParamsp->lfbPtr = (void *) lfbPtr;
511 ReadParamsp->LFBStrideInElts = strideInBytes / elementSize;
512 /*
513 * Now, calculate the value of firstWrappedX.
514 *
515 * The physical stride is the screen width in bytes rounded up to
516 * the next highest multiple of 128 bytes. Note that this fails
517 * when TILE_WIDTH_IN_BYTES is not a power of two.
518 *
519 * The buffer Offset is the distance between the beginning of
520 * the LFB space, which is the beginning of the back buffer,
521 * and the buffer we are gathering information about.
522 * We want to make this routine usable for operations on the
523 * back buffer, though we don't actually use it on the back
524 * buffer. Note, then, that if bufferOffset == 0, the firstWrappedX
525 * is in the forbidden zone, and is therefore never reached.
526 *
527 * Note that if
528 * physicalStrideInBytes
529 * < bufferOffset&(info->strideInBytes-1)
530 * the buffer begins in the forbidden zone. We assert for this.
531 */
532 bufferOffset = (FxU32)(lfbPtr - (char *) backBufferInfo->lfbPtr);
533 physicalStrideInBytes
534 = (fxMesa->screen_width * elementSize + TILE_WIDTH_IN_BYTES - 1)
535 & ~(TILE_WIDTH_IN_BYTES - 1);
536 assert(physicalStrideInBytes > (bufferOffset & (strideInBytes - 1)));
537 ReadParamsp->firstWrappedX
538 = (physicalStrideInBytes
539 - (bufferOffset & (strideInBytes - 1))) / elementSize;
540 /*
541 * This is the address of the next physical line.
542 */
543 ReadParamsp->lfbWrapPtr
544 = (void *) ((char *) backBufferInfo->lfbPtr
545 + (bufferOffset & ~(strideInBytes - 1))
546 + (TILE_HEIGHT_IN_LINES) * strideInBytes);
547 }
548
549 /*
550 * These macros fetch data from the frame buffer. The type is
551 * the type of data we want to fetch. It should match the type
552 * whose size was used with GetFbParams to fill in the structure
553 * in *ReadParamsp. We have a macro to read the ordinary
554 * part, a second macro to read the wrapped part, and one which
555 * will do either. When we are reading a span, we will know
556 * when the ordinary part ends, so there's no need to test for
557 * it. However, when reading and writing pixels, we don't
558 * necessarily know. I suppose it's a matter of taste whether
559 * it's better in the macro or in the call.
560 *
561 * Recall that x and y are screen coordinates.
562 */
563 #define GET_ORDINARY_FB_DATA(ReadParamsp, type, x, y) \
564 (((type *)((ReadParamsp)->lfbPtr)) \
565 [(y) * ((ReadParamsp)->LFBStrideInElts) \
566 + (x)])
567 #define GET_WRAPPED_FB_DATA(ReadParamsp, type, x, y) \
568 (((type *)((ReadParamsp)->lfbWrapPtr)) \
569 [((y)) * ((ReadParamsp)->LFBStrideInElts) \
570 + ((x) - (ReadParamsp)->firstWrappedX)])
571 #define GET_FB_DATA(ReadParamsp, type, x, y) \
572 (((x) < (ReadParamsp)->firstWrappedX) \
573 ? GET_ORDINARY_FB_DATA(ReadParamsp, type, x, y) \
574 : GET_WRAPPED_FB_DATA(ReadParamsp, type, x, y))
575 #define PUT_ORDINARY_FB_DATA(ReadParamsp, type, x, y, value) \
576 (GET_ORDINARY_FB_DATA(ReadParamsp, type, x, y) = (type)(value))
577 #define PUT_WRAPPED_FB_DATA(ReadParamsp, type, x, y, value) \
578 (GET_WRAPPED_FB_DATA(ReadParamsp, type, x, y) = (type)(value))
579 #define PUT_FB_DATA(ReadParamsp, type, x, y, value) \
580 do { \
581 if ((x) < (ReadParamsp)->firstWrappedX) \
582 PUT_ORDINARY_FB_DATA(ReadParamsp, type, x, y, value); \
583 else \
584 PUT_WRAPPED_FB_DATA(ReadParamsp, type, x, y, value); \
585 } while (0)
586
587
588 static void
589 tdfxDDWriteDepthSpan(GLcontext * ctx, struct gl_renderbuffer *rb,
590 GLuint n, GLint x, GLint y, const void *values,
591 const GLubyte mask[])
592 {
593 const GLuint *depth = (const GLuint *) values;
594 tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx;
595 GLint bottom = fxMesa->y_offset + fxMesa->height - 1;
596 GLuint depth_size = fxMesa->glCtx->Visual.depthBits;
597 GLuint stencil_size = fxMesa->glCtx->Visual.stencilBits;
598 GrLfbInfo_t info;
599 GLubyte visMask[MAX_WIDTH];
600
601 if (MESA_VERBOSE & VERBOSE_DRIVER) {
602 fprintf(stderr, "tdfxmesa: tdfxDDWriteDepthSpan(...)\n");
603 }
604
605 assert((depth_size == 16) || (depth_size == 24) || (depth_size == 32));
606 /*
607 * Convert x and y to screen coordinates.
608 */
609 x += fxMesa->x_offset;
610 y = bottom - y;
611 if (mask) {
612 GLint i;
613 GLushort d16;
614 GrLfbInfo_t backBufferInfo;
615
616 switch (depth_size) {
617 case 16:
618 GetBackBufferInfo(fxMesa, &backBufferInfo);
619 /*
620 * Note that the _LOCK macro adds a curly brace,
621 * and the UNLOCK macro removes it.
622 */
623 WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER,
624 GR_LFBWRITEMODE_ANY);
625 generate_vismask(fxMesa, x, y, n, visMask);
626 {
627 LFBParameters ReadParams;
628 int wrappedPartStart;
629 GetFbParams(fxMesa, &info, &backBufferInfo,
630 &ReadParams, sizeof(GLushort));
631 if (ReadParams.firstWrappedX <= x) {
632 wrappedPartStart = 0;
633 }
634 else if (n <= (ReadParams.firstWrappedX - x)) {
635 wrappedPartStart = n;
636 }
637 else {
638 wrappedPartStart = (ReadParams.firstWrappedX - x);
639 }
640 for (i = 0; i < wrappedPartStart; i++) {
641 if (mask[i] && visMask[i]) {
642 d16 = depth[i];
643 PUT_ORDINARY_FB_DATA(&ReadParams, GLushort, x + i, y, d16);
644 }
645 }
646 for (; i < n; i++) {
647 if (mask[i] && visMask[i]) {
648 d16 = depth[i];
649 PUT_WRAPPED_FB_DATA(&ReadParams, GLushort, x + i, y, d16);
650 }
651 }
652 }
653 WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
654 break;
655 case 24:
656 case 32:
657 GetBackBufferInfo(fxMesa, &backBufferInfo);
658 /*
659 * Note that the _LOCK macro adds a curly brace,
660 * and the UNLOCK macro removes it.
661 */
662 WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER,
663 GR_LFBWRITEMODE_ANY);
664 generate_vismask(fxMesa, x, y, n, visMask);
665 {
666 LFBParameters ReadParams;
667 int wrappedPartStart;
668 GetFbParams(fxMesa, &info, &backBufferInfo,
669 &ReadParams, sizeof(GLuint));
670 if (ReadParams.firstWrappedX <= x) {
671 wrappedPartStart = 0;
672 }
673 else if (n <= (ReadParams.firstWrappedX - x)) {
674 wrappedPartStart = n;
675 }
676 else {
677 wrappedPartStart = (ReadParams.firstWrappedX - x);
678 }
679 for (i = 0; i < wrappedPartStart; i++) {
680 GLuint d32;
681 if (mask[i] && visMask[i]) {
682 if (stencil_size > 0) {
683 d32 =
684 GET_ORDINARY_FB_DATA(&ReadParams, GLuint,
685 x + i, y);
686 d32 =
687 (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF);
688 }
689 else {
690 d32 = depth[i];
691 }
692 PUT_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y, d32);
693 }
694 }
695 for (; i < n; i++) {
696 GLuint d32;
697 if (mask[i] && visMask[i]) {
698 if (stencil_size > 0) {
699 d32 =
700 GET_WRAPPED_FB_DATA(&ReadParams, GLuint,
701 x + i, y);
702 d32 =
703 (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF);
704 }
705 else {
706 d32 = depth[i];
707 }
708 PUT_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y, d32);
709 }
710 }
711 }
712 WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
713 break;
714 }
715 }
716 else {
717 GLint i;
718 GLuint d32;
719 GLushort d16;
720 GrLfbInfo_t backBufferInfo;
721
722 switch (depth_size) {
723 case 16:
724 GetBackBufferInfo(fxMesa, &backBufferInfo);
725 /*
726 * Note that the _LOCK macro adds a curly brace,
727 * and the UNLOCK macro removes it.
728 */
729 WRITE_FB_SPAN_LOCK(fxMesa, info,
730 GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY);
731 generate_vismask(fxMesa, x, y, n, visMask);
732 {
733 LFBParameters ReadParams;
734 GLuint wrappedPartStart;
735 GetFbParams(fxMesa, &info, &backBufferInfo,
736 &ReadParams, sizeof(GLushort));
737 if (ReadParams.firstWrappedX <= x) {
738 wrappedPartStart = 0;
739 }
740 else if (n <= (ReadParams.firstWrappedX - x)) {
741 wrappedPartStart = n;
742 }
743 else {
744 wrappedPartStart = (ReadParams.firstWrappedX - x);
745 }
746 for (i = 0; i < wrappedPartStart; i++) {
747 if (visMask[i]) {
748 d16 = depth[i];
749 PUT_ORDINARY_FB_DATA(&ReadParams,
750 GLushort,
751 x + i, y,
752 d16);
753 }
754 }
755 for (; i < n; i++) {
756 if (visMask[i]) {
757 d16 = depth[i];
758 PUT_WRAPPED_FB_DATA(&ReadParams,
759 GLushort,
760 x + i, y,
761 d16);
762 }
763 }
764 }
765 WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
766 break;
767 case 24:
768 case 32:
769 GetBackBufferInfo(fxMesa, &backBufferInfo);
770 /*
771 * Note that the _LOCK macro adds a curly brace,
772 * and the UNLOCK macro removes it.
773 */
774 WRITE_FB_SPAN_LOCK(fxMesa, info,
775 GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY);
776 generate_vismask(fxMesa, x, y, n, visMask);
777 {
778 LFBParameters ReadParams;
779 GLuint wrappedPartStart;
780
781 GetFbParams(fxMesa, &info, &backBufferInfo,
782 &ReadParams, sizeof(GLuint));
783 if (ReadParams.firstWrappedX <= x) {
784 wrappedPartStart = 0;
785 }
786 else if (n <= (ReadParams.firstWrappedX - x)) {
787 wrappedPartStart = n;
788 }
789 else {
790 wrappedPartStart = (ReadParams.firstWrappedX - x);
791 }
792 for (i = 0; i < wrappedPartStart; i++) {
793 if (visMask[i]) {
794 if (stencil_size > 0) {
795 d32 = GET_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y);
796 d32 =
797 (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF);
798 }
799 else {
800 d32 = depth[i];
801 }
802 PUT_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y, d32);
803 }
804 }
805 for (; i < n; i++) {
806 if (visMask[i]) {
807 if (stencil_size > 0) {
808 d32 = GET_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y);
809 d32 =
810 (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF);
811 }
812 else {
813 d32 = depth[i];
814 }
815 PUT_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y, d32);
816 }
817 }
818 }
819 WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
820 break;
821 }
822 }
823 }
824
825 static void
826 tdfxDDWriteMonoDepthSpan(GLcontext * ctx, struct gl_renderbuffer *rb,
827 GLuint n, GLint x, GLint y, const void *value,
828 const GLubyte mask[])
829 {
830 GLuint depthVal = *((GLuint *) value);
831 GLuint depths[MAX_WIDTH];
832 GLuint i;
833 for (i = 0; i < n; i++)
834 depths[i] = depthVal;
835 tdfxDDWriteDepthSpan(ctx, rb, n, x, y, depths, mask);
836 }
837
838
839 static void
840 tdfxDDReadDepthSpan(GLcontext * ctx, struct gl_renderbuffer *rb,
841 GLuint n, GLint x, GLint y, void *values)
842 {
843 GLuint *depth = (GLuint *) values;
844 tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx;
845 GLint bottom = fxMesa->height + fxMesa->y_offset - 1;
846 GLuint i;
847 GLuint depth_size = fxMesa->glCtx->Visual.depthBits;
848 GrLfbInfo_t info;
849
850 if (MESA_VERBOSE & VERBOSE_DRIVER) {
851 fprintf(stderr, "tdfxmesa: tdfxDDReadDepthSpan(...)\n");
852 }
853
854 /*
855 * Convert to screen coordinates.
856 */
857 x += fxMesa->x_offset;
858 y = bottom - y;
859 switch (depth_size) {
860 case 16:
861 {
862 LFBParameters ReadParams;
863 GrLfbInfo_t backBufferInfo;
864 int wrappedPartStart;
865 GetBackBufferInfo(fxMesa, &backBufferInfo);
866 /*
867 * Note that the _LOCK macro adds a curly brace,
868 * and the UNLOCK macro removes it.
869 */
870 READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER);
871 GetFbParams(fxMesa, &info, &backBufferInfo,
872 &ReadParams, sizeof(GLushort));
873 if (ReadParams.firstWrappedX <= x) {
874 wrappedPartStart = 0;
875 }
876 else if (n <= (ReadParams.firstWrappedX - x)) {
877 wrappedPartStart = n;
878 }
879 else {
880 wrappedPartStart = (ReadParams.firstWrappedX - x);
881 }
882 /*
883 * Read the line.
884 */
885 for (i = 0; i < wrappedPartStart; i++) {
886 depth[i] =
887 GET_ORDINARY_FB_DATA(&ReadParams, GLushort, x + i, y);
888 }
889 for (; i < n; i++) {
890 depth[i] = GET_WRAPPED_FB_DATA(&ReadParams, GLushort,
891 x + i, y);
892 }
893 READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
894 break;
895 }
896 case 24:
897 case 32:
898 {
899 LFBParameters ReadParams;
900 GrLfbInfo_t backBufferInfo;
901 int wrappedPartStart;
902 GLuint stencil_size = fxMesa->glCtx->Visual.stencilBits;
903 GetBackBufferInfo(fxMesa, &backBufferInfo);
904 /*
905 * Note that the _LOCK macro adds a curly brace,
906 * and the UNLOCK macro removes it.
907 */
908 READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER);
909 GetFbParams(fxMesa, &info, &backBufferInfo,
910 &ReadParams, sizeof(GLuint));
911 if (ReadParams.firstWrappedX <= x) {
912 wrappedPartStart = 0;
913 }
914 else if (n <= (ReadParams.firstWrappedX - x)) {
915 wrappedPartStart = n;
916 }
917 else {
918 wrappedPartStart = (ReadParams.firstWrappedX - x);
919 }
920 /*
921 * Read the line.
922 */
923 for (i = 0; i < wrappedPartStart; i++) {
924 const GLuint mask =
925 (stencil_size > 0) ? 0x00FFFFFF : 0xFFFFFFFF;
926 depth[i] =
927 GET_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y);
928 depth[i] &= mask;
929 }
930 for (; i < n; i++) {
931 const GLuint mask =
932 (stencil_size > 0) ? 0x00FFFFFF : 0xFFFFFFFF;
933 depth[i] = GET_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y);
934 depth[i] &= mask;
935 }
936 READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
937 break;
938 }
939 }
940 }
941
942
943 static void
944 tdfxDDWriteDepthPixels(GLcontext * ctx, struct gl_renderbuffer *rb,
945 GLuint n, const GLint x[], const GLint y[],
946 const void *values, const GLubyte mask[])
947 {
948 const GLuint *depth = (const GLuint *) values;
949 tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx;
950 GLint bottom = fxMesa->height + fxMesa->y_offset - 1;
951 GLuint i;
952 GLushort d16;
953 GLuint d32;
954 GLuint depth_size = fxMesa->glCtx->Visual.depthBits;
955 GLuint stencil_size = fxMesa->glCtx->Visual.stencilBits;
956 GrLfbInfo_t info;
957 int xpos;
958 int ypos;
959 GrLfbInfo_t backBufferInfo;
960
961 if (MESA_VERBOSE & VERBOSE_DRIVER) {
962 fprintf(stderr, "tdfxmesa: tdfxDDWriteDepthPixels(...)\n");
963 }
964
965 switch (depth_size) {
966 case 16:
967 GetBackBufferInfo(fxMesa, &backBufferInfo);
968 /*
969 * Note that the _LOCK macro adds a curly brace,
970 * and the UNLOCK macro removes it.
971 */
972 WRITE_FB_SPAN_LOCK(fxMesa, info,
973 GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY);
974 {
975 LFBParameters ReadParams;
976 GetFbParams(fxMesa, &info, &backBufferInfo,
977 &ReadParams, sizeof(GLushort));
978 for (i = 0; i < n; i++) {
979 if (mask[i] && visible_pixel(fxMesa, x[i], y[i])) {
980 xpos = x[i] + fxMesa->x_offset;
981 ypos = bottom - y[i];
982 d16 = depth[i];
983 PUT_FB_DATA(&ReadParams, GLushort, xpos, ypos, d16);
984 }
985 }
986 }
987 WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
988 break;
989 case 24:
990 case 32:
991 GetBackBufferInfo(fxMesa, &backBufferInfo);
992 /*
993 * Note that the _LOCK macro adds a curly brace,
994 * and the UNLOCK macro removes it.
995 */
996 WRITE_FB_SPAN_LOCK(fxMesa, info,
997 GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY);
998 {
999 LFBParameters ReadParams;
1000 GetFbParams(fxMesa, &info, &backBufferInfo,
1001 &ReadParams, sizeof(GLuint));
1002 for (i = 0; i < n; i++) {
1003 if (mask[i]) {
1004 if (visible_pixel(fxMesa, x[i], y[i])) {
1005 xpos = x[i] + fxMesa->x_offset;
1006 ypos = bottom - y[i];
1007 if (stencil_size > 0) {
1008 d32 =
1009 GET_FB_DATA(&ReadParams, GLuint, xpos, ypos);
1010 d32 = (d32 & 0xFF000000) | (depth[i] & 0xFFFFFF);
1011 }
1012 else {
1013 d32 = depth[i];
1014 }
1015 PUT_FB_DATA(&ReadParams, GLuint, xpos, ypos, d32);
1016 }
1017 }
1018 }
1019 }
1020 WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
1021 break;
1022 }
1023 }
1024
1025
1026 static void
1027 tdfxDDReadDepthPixels(GLcontext * ctx, struct gl_renderbuffer *rb, GLuint n,
1028 const GLint x[], const GLint y[], void *values)
1029 {
1030 GLuint *depth = (GLuint *) values;
1031 tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx;
1032 GLint bottom = fxMesa->height + fxMesa->y_offset - 1;
1033 GLuint i;
1034 GLuint depth_size = fxMesa->glCtx->Visual.depthBits;
1035 GLushort d16;
1036 int xpos;
1037 int ypos;
1038 GrLfbInfo_t info;
1039 GLuint stencil_size;
1040 GrLfbInfo_t backBufferInfo;
1041
1042 if (MESA_VERBOSE & VERBOSE_DRIVER) {
1043 fprintf(stderr, "tdfxmesa: tdfxDDReadDepthPixels(...)\n");
1044 }
1045
1046 assert((depth_size == 16) || (depth_size == 24) || (depth_size == 32));
1047 switch (depth_size) {
1048 case 16:
1049 GetBackBufferInfo(fxMesa, &backBufferInfo);
1050 /*
1051 * Note that the _LOCK macro adds a curly brace,
1052 * and the UNLOCK macro removes it.
1053 */
1054 READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER);
1055 {
1056 LFBParameters ReadParams;
1057 GetFbParams(fxMesa, &info, &backBufferInfo,
1058 &ReadParams, sizeof(GLushort));
1059 for (i = 0; i < n; i++) {
1060 /*
1061 * Convert to screen coordinates.
1062 */
1063 xpos = x[i] + fxMesa->x_offset;
1064 ypos = bottom - y[i];
1065 d16 = GET_FB_DATA(&ReadParams, GLushort, xpos, ypos);
1066 depth[i] = d16;
1067 }
1068 }
1069 READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
1070 break;
1071 case 24:
1072 case 32:
1073 GetBackBufferInfo(fxMesa, &backBufferInfo);
1074 /*
1075 * Note that the _LOCK macro adds a curly brace,
1076 * and the UNLOCK macro removes it.
1077 */
1078 READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER);
1079 stencil_size = fxMesa->glCtx->Visual.stencilBits;
1080 {
1081 LFBParameters ReadParams;
1082 GetFbParams(fxMesa, &info, &backBufferInfo,
1083 &ReadParams, sizeof(GLuint));
1084 for (i = 0; i < n; i++) {
1085 GLuint d32;
1086
1087 /*
1088 * Convert to screen coordinates.
1089 */
1090 xpos = x[i] + fxMesa->x_offset;
1091 ypos = bottom - y[i];
1092 d32 = GET_FB_DATA(&ReadParams, GLuint, xpos, ypos);
1093 if (stencil_size > 0) {
1094 d32 &= 0x00FFFFFF;
1095 }
1096 depth[i] = d32;
1097 }
1098 }
1099 READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
1100 break;
1101 default:
1102 assert(0);
1103 }
1104 }
1105
1106 /*
1107 * Stencil buffer read/write functions.
1108 */
1109 #define EXTRACT_S_FROM_ZS(zs) (((zs) >> 24) & 0xFF)
1110 #define EXTRACT_Z_FROM_ZS(zs) ((zs) & 0xffffff)
1111 #define BUILD_ZS(z, s) (((s) << 24) | (z))
1112
1113 static void
1114 write_stencil_span(GLcontext * ctx, struct gl_renderbuffer *rb,
1115 GLuint n, GLint x, GLint y,
1116 const void *values, const GLubyte mask[])
1117 {
1118 const GLubyte *stencil = (const GLubyte *) values;
1119 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1120 GrLfbInfo_t info;
1121 GrLfbInfo_t backBufferInfo;
1122
1123 GetBackBufferInfo(fxMesa, &backBufferInfo);
1124 /*
1125 * Note that the _LOCK macro adds a curly brace,
1126 * and the UNLOCK macro removes it.
1127 */
1128 WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY);
1129 {
1130 const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
1131 const GLint winX = fxMesa->x_offset;
1132 const GLint scrX = winX + x;
1133 const GLint scrY = winY - y;
1134 LFBParameters ReadParams;
1135 GLubyte visMask[MAX_WIDTH];
1136 GLuint i;
1137 int wrappedPartStart;
1138
1139 GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams,
1140 sizeof(GLuint));
1141 if (ReadParams.firstWrappedX <= x) {
1142 wrappedPartStart = 0;
1143 }
1144 else if (n <= (ReadParams.firstWrappedX - x)) {
1145 wrappedPartStart = n;
1146 }
1147 else {
1148 wrappedPartStart = (ReadParams.firstWrappedX - x);
1149 }
1150 generate_vismask(fxMesa, scrX, scrY, n, visMask);
1151 for (i = 0; i < wrappedPartStart; i++) {
1152 if (visMask[i] && (!mask || mask[i])) {
1153 GLuint z = GET_ORDINARY_FB_DATA(&ReadParams, GLuint,
1154 scrX + i, scrY) & 0x00FFFFFF;
1155 z |= (stencil[i] & 0xFF) << 24;
1156 PUT_ORDINARY_FB_DATA(&ReadParams, GLuint, scrX + i, scrY, z);
1157 }
1158 }
1159 for (; i < n; i++) {
1160 if (visMask[i] && (!mask || mask[i])) {
1161 GLuint z = GET_WRAPPED_FB_DATA(&ReadParams, GLuint,
1162 scrX + i, scrY) & 0x00FFFFFF;
1163 z |= (stencil[i] & 0xFF) << 24;
1164 PUT_WRAPPED_FB_DATA(&ReadParams, GLuint, scrX + i, scrY, z);
1165 }
1166 }
1167 }
1168 WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
1169 }
1170
1171
1172 static void
1173 write_mono_stencil_span(GLcontext * ctx, struct gl_renderbuffer *rb,
1174 GLuint n, GLint x, GLint y,
1175 const void *value, const GLubyte mask[])
1176 {
1177 GLbyte stencilVal = *((GLbyte *) value);
1178 GLbyte stencils[MAX_WIDTH];
1179 GLuint i;
1180 for (i = 0; i < n; i++)
1181 stencils[i] = stencilVal;
1182 write_stencil_span(ctx, rb, n, x, y, stencils, mask);
1183 }
1184
1185
1186 static void
1187 read_stencil_span(GLcontext * ctx, struct gl_renderbuffer *rb,
1188 GLuint n, GLint x, GLint y,
1189 void *values)
1190 {
1191 GLubyte *stencil = (GLubyte *) values;
1192 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1193 GrLfbInfo_t info;
1194 GrLfbInfo_t backBufferInfo;
1195
1196 GetBackBufferInfo(fxMesa, &backBufferInfo);
1197 /*
1198 * Note that the _LOCK macro adds a curly brace,
1199 * and the UNLOCK macro removes it.
1200 */
1201 READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER);
1202 {
1203 const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
1204 const GLint winX = fxMesa->x_offset;
1205 GLuint i;
1206 LFBParameters ReadParams;
1207 int wrappedPartStart;
1208
1209 /*
1210 * Convert to screen coordinates.
1211 */
1212 x += winX;
1213 y = winY - y;
1214 GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams,
1215 sizeof(GLuint));
1216 if (ReadParams.firstWrappedX <= x) {
1217 wrappedPartStart = 0;
1218 }
1219 else if (n <= (ReadParams.firstWrappedX - x)) {
1220 wrappedPartStart = n;
1221 }
1222 else {
1223 wrappedPartStart = (ReadParams.firstWrappedX - x);
1224 }
1225 for (i = 0; i < wrappedPartStart; i++) {
1226 stencil[i] = (GET_ORDINARY_FB_DATA(&ReadParams, GLuint,
1227 x + i, y) >> 24) & 0xFF;
1228 }
1229 for (; i < n; i++) {
1230 stencil[i] = (GET_WRAPPED_FB_DATA(&ReadParams, GLuint,
1231 x + i, y) >> 24) & 0xFF;
1232 }
1233 }
1234 READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
1235 }
1236
1237
1238 static void
1239 write_stencil_pixels(GLcontext * ctx, struct gl_renderbuffer *rb,
1240 GLuint n, const GLint x[], const GLint y[],
1241 const void *values, const GLubyte mask[])
1242 {
1243 const GLubyte *stencil = (const GLubyte *) values;
1244 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1245 GrLfbInfo_t info;
1246 GrLfbInfo_t backBufferInfo;
1247
1248 GetBackBufferInfo(fxMesa, &backBufferInfo);
1249 /*
1250 * Note that the _LOCK macro adds a curly brace,
1251 * and the UNLOCK macro removes it.
1252 */
1253 WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY);
1254 {
1255 const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
1256 const GLint winX = fxMesa->x_offset;
1257 LFBParameters ReadParams;
1258 GLuint i;
1259
1260 GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams,
1261 sizeof(GLuint));
1262 for (i = 0; i < n; i++) {
1263 const GLint scrX = winX + x[i];
1264 const GLint scrY = winY - y[i];
1265 if ((!mask || mask[i]) && visible_pixel(fxMesa, scrX, scrY)) {
1266 GLuint z =
1267 GET_FB_DATA(&ReadParams, GLuint, scrX, scrY) & 0x00FFFFFF;
1268 z |= (stencil[i] & 0xFF) << 24;
1269 PUT_FB_DATA(&ReadParams, GLuint, scrX, scrY, z);
1270 }
1271 }
1272 }
1273 WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
1274 }
1275
1276
1277 static void
1278 read_stencil_pixels(GLcontext * ctx, struct gl_renderbuffer *rb,
1279 GLuint n, const GLint x[], const GLint y[],
1280 void *values)
1281 {
1282 GLubyte *stencil = (GLubyte *) values;
1283 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1284 GrLfbInfo_t info;
1285 GrLfbInfo_t backBufferInfo;
1286
1287 GetBackBufferInfo(fxMesa, &backBufferInfo);
1288 /*
1289 * Note that the _LOCK macro adds a curly brace,
1290 * and the UNLOCK macro removes it.
1291 */
1292 READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER);
1293 {
1294 const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
1295 const GLint winX = fxMesa->x_offset;
1296 GLuint i;
1297 LFBParameters ReadParams;
1298
1299 GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams,
1300 sizeof(GLuint));
1301 for (i = 0; i < n; i++) {
1302 const GLint scrX = winX + x[i];
1303 const GLint scrY = winY - y[i];
1304 stencil[i] =
1305 (GET_FB_DATA(&ReadParams, GLuint, scrX, scrY) >> 24) & 0xFF;
1306 }
1307 }
1308 READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER);
1309 }
1310
1311 #define VISUAL_EQUALS_RGBA(vis, r, g, b, a) \
1312 ((vis.redBits == r) && \
1313 (vis.greenBits == g) && \
1314 (vis.blueBits == b) && \
1315 (vis.alphaBits == a))
1316
1317
1318
1319
1320 /**********************************************************************/
1321 /* Locking for swrast */
1322 /**********************************************************************/
1323
1324
1325 static void tdfxSpanRenderStart( GLcontext *ctx )
1326 {
1327 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1328 LOCK_HARDWARE(fxMesa);
1329 }
1330
1331 static void tdfxSpanRenderFinish( GLcontext *ctx )
1332 {
1333 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1334 _swrast_flush( ctx );
1335 UNLOCK_HARDWARE(fxMesa);
1336 }
1337
1338 /**********************************************************************/
1339 /* Initialize swrast device driver */
1340 /**********************************************************************/
1341
1342 void tdfxDDInitSpanFuncs( GLcontext *ctx )
1343 {
1344 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
1345 swdd->SpanRenderStart = tdfxSpanRenderStart;
1346 swdd->SpanRenderFinish = tdfxSpanRenderFinish;
1347 }
1348
1349
1350
1351 /**
1352 * Plug in the Get/Put routines for the given driRenderbuffer.
1353 */
1354 void
1355 tdfxSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
1356 {
1357 if (drb->Base.InternalFormat == GL_RGBA) {
1358 if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
1359 tdfxInitPointers_RGB565(&drb->Base);
1360 }
1361 else if (vis->redBits == 8 && vis->greenBits == 8
1362 && vis->blueBits == 8 && vis->alphaBits == 0) {
1363 tdfxInitPointers_RGB888(&drb->Base);
1364 }
1365 else if (vis->redBits == 8 && vis->greenBits == 8
1366 && vis->blueBits == 8 && vis->alphaBits == 8) {
1367 tdfxInitPointers_ARGB8888(&drb->Base);
1368 }
1369 else {
1370 _mesa_problem(NULL, "problem in tdfxSetSpanFunctions");
1371 }
1372 }
1373 else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16 ||
1374 drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
1375 drb->Base.GetRow = tdfxDDReadDepthSpan;
1376 drb->Base.GetValues = tdfxDDReadDepthPixels;
1377 drb->Base.PutRow = tdfxDDWriteDepthSpan;
1378 drb->Base.PutMonoRow = tdfxDDWriteMonoDepthSpan;
1379 drb->Base.PutValues = tdfxDDWriteDepthPixels;
1380 drb->Base.PutMonoValues = NULL;
1381 }
1382 else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
1383 drb->Base.GetRow = read_stencil_span;
1384 drb->Base.GetValues = read_stencil_pixels;
1385 drb->Base.PutRow = write_stencil_span;
1386 drb->Base.PutMonoRow = write_mono_stencil_span;
1387 drb->Base.PutValues = write_stencil_pixels;
1388 drb->Base.PutMonoValues = NULL;
1389 }
1390 }