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