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