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