b59706118e451c0cf8c277fb6278e8e1c5e9001a
[mesa.git] / src / mesa / drivers / dri / r128 / r128_span.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_span.c,v 1.8 2002/10/30 12:51:39 alanh Exp $ */
2 /**************************************************************************
3
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
5 Cedar Park, Texas.
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Gareth Hughes <gareth@valinux.com>
32 * Keith Whitwell <keith@tungstengraphics.com>
33 * Kevin E. Martin <martin@valinux.com>
34 *
35 */
36
37 #include "r128_context.h"
38 #include "r128_ioctl.h"
39 #include "r128_state.h"
40 #include "r128_span.h"
41 #include "r128_tex.h"
42
43 #include "swrast/swrast.h"
44
45 #define DBG 0
46
47 #define HAVE_HW_DEPTH_SPANS 1
48 #define HAVE_HW_DEPTH_PIXELS 1
49
50 #define LOCAL_VARS \
51 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
52 r128ScreenPtr r128scrn = rmesa->r128Screen; \
53 __DRIscreenPrivate *sPriv = rmesa->driScreen; \
54 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
55 GLuint pitch = r128scrn->frontPitch * r128scrn->cpp; \
56 GLuint height = dPriv->h; \
57 char *buf = (char *)(sPriv->pFB + \
58 rmesa->drawOffset + \
59 (dPriv->x * r128scrn->cpp) + \
60 (dPriv->y * pitch)); \
61 char *read_buf = (char *)(sPriv->pFB + \
62 rmesa->readOffset + \
63 (dPriv->x * r128scrn->cpp) + \
64 (dPriv->y * pitch)); \
65 GLuint p; \
66 (void) read_buf; (void) buf; (void) p
67
68 #define LOCAL_DEPTH_VARS \
69 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
70 r128ScreenPtr r128scrn = rmesa->r128Screen; \
71 __DRIscreenPrivate *sPriv = rmesa->driScreen; \
72 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
73 GLuint height = dPriv->h; \
74 (void) r128scrn; (void) sPriv; (void) height
75
76 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
77
78
79 #define CLIPPIXEL( _x, _y ) \
80 ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
81
82
83 #define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
84 if ( _y < miny || _y >= maxy ) { \
85 _n1 = 0, _x1 = x; \
86 } else { \
87 _n1 = _n; \
88 _x1 = _x; \
89 if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
90 if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
91 }
92
93 #define Y_FLIP( _y ) (height - _y - 1)
94
95
96 #define HW_LOCK() \
97 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
98 FLUSH_BATCH( rmesa ); \
99 LOCK_HARDWARE( rmesa ); \
100 r128WaitForIdleLocked( rmesa );
101
102 #define HW_CLIPLOOP() \
103 do { \
104 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
105 int _nc = dPriv->numClipRects; \
106 \
107 while ( _nc-- ) { \
108 int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
109 int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
110 int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
111 int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
112
113 #define HW_ENDCLIPLOOP() \
114 } \
115 } while (0)
116
117 #define HW_UNLOCK() \
118 UNLOCK_HARDWARE( rmesa )
119
120
121
122 /* ================================================================
123 * Color buffer
124 */
125
126 /* 16 bit, RGB565 color spanline and pixel functions
127 */
128 #define GET_SRC_PTR(_x, _y) (read_buf + _x * 2 + _y * pitch)
129 #define GET_DST_PTR(_x, _y) ( buf + _x * 2 + _y * pitch)
130 #define SPANTMP_PIXEL_FMT GL_RGB
131 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
132
133 #define TAG(x) r128##x##_RGB565
134 #define TAG2(x,y) r128##x##_RGB565##y
135 #include "spantmp2.h"
136
137
138 /* 32 bit, ARGB8888 color spanline and pixel functions
139 */
140 #define GET_SRC_PTR(_x, _y) (read_buf + _x * 4 + _y * pitch)
141 #define GET_DST_PTR(_x, _y) ( buf + _x * 4 + _y * pitch)
142 #define SPANTMP_PIXEL_FMT GL_BGRA
143 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
144
145 #define TAG(x) r128##x##_ARGB8888
146 #define TAG2(x,y) r128##x##_ARGB8888##y
147 #include "spantmp2.h"
148
149
150 /* ================================================================
151 * Depth buffer
152 */
153
154 /* 16-bit depth buffer functions
155 */
156 #define READ_DEPTH(d, _x, _y) \
157 d = *(GLushort *)(buf + (_x)*2 + (_y)*pitch)
158
159 #define WRITE_DEPTH_SPAN() \
160 r128WriteDepthSpanLocked( rmesa, n, \
161 x + dPriv->x, \
162 y + dPriv->y, \
163 depth, mask );
164
165 #define WRITE_DEPTH_PIXELS() \
166 do { \
167 GLint ox[MAX_WIDTH]; \
168 GLint oy[MAX_WIDTH]; \
169 for ( i = 0 ; i < n ; i++ ) { \
170 ox[i] = x[i] + dPriv->x; \
171 } \
172 for ( i = 0 ; i < n ; i++ ) { \
173 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
174 } \
175 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
176 } while (0)
177
178 #define READ_DEPTH_SPAN() \
179 do { \
180 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
181 r128scrn->spanOffset); \
182 GLint i; \
183 \
184 r128ReadDepthSpanLocked( rmesa, n, \
185 x + dPriv->x, \
186 y + dPriv->y ); \
187 r128WaitForIdleLocked( rmesa ); \
188 \
189 for ( i = 0 ; i < n ; i++ ) { \
190 depth[i] = buf[i]; \
191 } \
192 } while (0)
193
194 #define READ_DEPTH_PIXELS() \
195 do { \
196 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
197 r128scrn->spanOffset); \
198 GLint i, remaining = n; \
199 \
200 while ( remaining > 0 ) { \
201 GLint ox[MAX_WIDTH]; \
202 GLint oy[MAX_WIDTH]; \
203 GLint count; \
204 \
205 if ( remaining <= 128 ) { \
206 count = remaining; \
207 } else { \
208 count = 128; \
209 } \
210 for ( i = 0 ; i < count ; i++ ) { \
211 ox[i] = x[i] + dPriv->x; \
212 } \
213 for ( i = 0 ; i < count ; i++ ) { \
214 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
215 } \
216 \
217 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
218 r128WaitForIdleLocked( rmesa ); \
219 \
220 for ( i = 0 ; i < count ; i++ ) { \
221 depth[i] = buf[i]; \
222 } \
223 depth += count; \
224 x += count; \
225 y += count; \
226 remaining -= count; \
227 } \
228 } while (0)
229
230 #define TAG(x) r128##x##_16
231 #include "depthtmp.h"
232
233
234 /* 24-bit depth, 8-bit stencil buffer functions
235 */
236 #define WRITE_DEPTH_SPAN() \
237 r128WriteDepthSpanLocked( rmesa, n, \
238 x + dPriv->x, \
239 y + dPriv->y, \
240 depth, mask );
241
242 #define WRITE_DEPTH_PIXELS() \
243 do { \
244 GLint ox[MAX_WIDTH]; \
245 GLint oy[MAX_WIDTH]; \
246 for ( i = 0 ; i < n ; i++ ) { \
247 ox[i] = x[i] + dPriv->x; \
248 } \
249 for ( i = 0 ; i < n ; i++ ) { \
250 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
251 } \
252 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
253 } while (0)
254
255 #define READ_DEPTH_SPAN() \
256 do { \
257 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
258 r128scrn->spanOffset); \
259 GLint i; \
260 \
261 r128ReadDepthSpanLocked( rmesa, n, \
262 x + dPriv->x, \
263 y + dPriv->y ); \
264 r128WaitForIdleLocked( rmesa ); \
265 \
266 for ( i = 0 ; i < n ; i++ ) { \
267 depth[i] = buf[i] & 0x00ffffff; \
268 } \
269 } while (0)
270
271 #define READ_DEPTH_PIXELS() \
272 do { \
273 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
274 r128scrn->spanOffset); \
275 GLint i, remaining = n; \
276 \
277 while ( remaining > 0 ) { \
278 GLint ox[MAX_WIDTH]; \
279 GLint oy[MAX_WIDTH]; \
280 GLint count; \
281 \
282 if ( remaining <= 128 ) { \
283 count = remaining; \
284 } else { \
285 count = 128; \
286 } \
287 for ( i = 0 ; i < count ; i++ ) { \
288 ox[i] = x[i] + dPriv->x; \
289 } \
290 for ( i = 0 ; i < count ; i++ ) { \
291 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
292 } \
293 \
294 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
295 r128WaitForIdleLocked( rmesa ); \
296 \
297 for ( i = 0 ; i < count ; i++ ) { \
298 depth[i] = buf[i] & 0x00ffffff; \
299 } \
300 depth += count; \
301 x += count; \
302 y += count; \
303 remaining -= count; \
304 } \
305 } while (0)
306
307 #define TAG(x) r128##x##_24_8
308 #include "depthtmp.h"
309
310
311
312 /* ================================================================
313 * Stencil buffer
314 */
315
316 /* FIXME: Add support for hardware stencil buffers.
317 */
318
319
320 /* 32 bit depthbuffer functions */
321 #define WRITE_DEPTH(_x, _y, d) \
322 *(GLuint *)(buf + _x*4 + _y*pitch) = d
323
324
325
326 /*
327 * This function is called to specify which buffer to read and write
328 * for software rasterization (swrast) fallbacks. This doesn't necessarily
329 * correspond to glDrawBuffer() or glReadBuffer() calls.
330 */
331 static void r128DDSetBuffer( GLcontext *ctx,
332 GLframebuffer *colorBuffer,
333 GLuint bufferBit )
334 {
335 r128ContextPtr rmesa = R128_CONTEXT(ctx);
336
337 switch ( bufferBit ) {
338 case BUFFER_BIT_FRONT_LEFT:
339 if ( rmesa->sarea->pfCurrentPage == 1 ) {
340 rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
341 rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
342 } else {
343 rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
344 rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
345 }
346 break;
347 case BUFFER_BIT_BACK_LEFT:
348 if ( rmesa->sarea->pfCurrentPage == 1 ) {
349 rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
350 rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
351 } else {
352 rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
353 rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
354 }
355 break;
356 default:
357 break;
358 }
359 }
360
361
362 void r128DDInitSpanFuncs( GLcontext *ctx )
363 {
364 r128ContextPtr rmesa = R128_CONTEXT(ctx);
365 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
366
367 swdd->SetBuffer = r128DDSetBuffer;
368
369 switch ( rmesa->r128Screen->cpp ) {
370 case 2:
371 #if 0
372 r128InitPointers_RGB565( swdd );
373 #endif
374 break;
375
376 case 4:
377 #if 0
378 r128InitPointers_ARGB8888( swdd );
379 #endif
380 break;
381
382 default:
383 break;
384 }
385
386 switch ( rmesa->glCtx->Visual.depthBits ) {
387 case 16:
388 #if 0
389 swdd->ReadDepthSpan = r128ReadDepthSpan_16;
390 swdd->WriteDepthSpan = r128WriteDepthSpan_16;
391 swdd->ReadDepthPixels = r128ReadDepthPixels_16;
392 swdd->WriteDepthPixels = r128WriteDepthPixels_16;
393 #endif
394 break;
395
396 case 24:
397 #if 0
398 swdd->ReadDepthSpan = r128ReadDepthSpan_24_8;
399 swdd->WriteDepthSpan = r128WriteDepthSpan_24_8;
400 swdd->ReadDepthPixels = r128ReadDepthPixels_24_8;
401 swdd->WriteDepthPixels = r128WriteDepthPixels_24_8;
402 #endif
403 break;
404
405 default:
406 break;
407 }
408
409 swdd->WriteCI8Span = NULL;
410 swdd->WriteCI32Span = NULL;
411 swdd->WriteMonoCISpan = NULL;
412 swdd->WriteCI32Pixels = NULL;
413 swdd->WriteMonoCIPixels = NULL;
414 swdd->ReadCI32Span = NULL;
415 swdd->ReadCI32Pixels = NULL;
416 }
417
418
419 /**
420 * Plug in the Get/Put routines for the given driRenderbuffer.
421 */
422 void
423 r128SetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
424 {
425 if (drb->Base.InternalFormat == GL_RGBA) {
426 if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
427 r128InitPointers_RGB565(&drb->Base);
428 }
429 else {
430 r128InitPointers_ARGB8888(&drb->Base);
431 }
432 }
433 else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
434 drb->Base.GetRow = r128ReadDepthSpan_16;
435 drb->Base.GetValues = r128ReadDepthPixels_16;
436 drb->Base.PutRow = r128WriteDepthSpan_16;
437 drb->Base.PutMonoRow = r128WriteMonoDepthSpan_16;
438 drb->Base.PutValues = r128WriteDepthPixels_16;
439 drb->Base.PutMonoValues = NULL;
440 }
441 else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
442 drb->Base.GetRow = r128ReadDepthSpan_24_8;
443 drb->Base.GetValues = r128ReadDepthPixels_24_8;
444 drb->Base.PutRow = r128WriteDepthSpan_24_8;
445 drb->Base.PutMonoRow = r128WriteMonoDepthSpan_24_8;
446 drb->Base.PutValues = r128WriteDepthPixels_24_8;
447 drb->Base.PutMonoValues = NULL;
448 }
449 else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
450 drb->Base.GetRow = NULL;
451 drb->Base.GetValues = NULL;
452 drb->Base.PutRow = NULL;
453 drb->Base.PutMonoRow = NULL;
454 drb->Base.PutValues = NULL;
455 drb->Base.PutMonoValues = NULL;
456 }
457 }