Remove CVS keywords.
[mesa.git] / src / mesa / drivers / dri / r128 / r128_span.c
1 /**************************************************************************
2
3 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
4 Cedar Park, Texas.
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 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Gareth Hughes <gareth@valinux.com>
31 * Keith Whitwell <keith@tungstengraphics.com>
32 * Kevin E. Martin <martin@valinux.com>
33 *
34 */
35
36 #include "r128_context.h"
37 #include "r128_ioctl.h"
38 #include "r128_state.h"
39 #include "r128_span.h"
40 #include "r128_tex.h"
41
42 #include "swrast/swrast.h"
43
44 #define DBG 0
45
46 #define HAVE_HW_DEPTH_SPANS 1
47 #define HAVE_HW_DEPTH_PIXELS 1
48 #define HAVE_HW_STENCIL_SPANS 1
49 #define HAVE_HW_STENCIL_PIXELS 1
50
51 #define LOCAL_VARS \
52 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
53 __DRIscreenPrivate *sPriv = rmesa->driScreen; \
54 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
55 driRenderbuffer *drb = (driRenderbuffer *) rb; \
56 GLuint height = dPriv->h; \
57 GLuint p; \
58 (void) p;
59
60 #define LOCAL_DEPTH_VARS \
61 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
62 r128ScreenPtr r128scrn = rmesa->r128Screen; \
63 __DRIscreenPrivate *sPriv = rmesa->driScreen; \
64 __DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
65 GLuint height = dPriv->h; \
66 (void) r128scrn; (void) sPriv; (void) height
67
68 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
69
70 #define Y_FLIP( _y ) (height - _y - 1)
71
72 #define HW_LOCK()
73
74 #define HW_UNLOCK()
75
76
77
78 /* ================================================================
79 * Color buffer
80 */
81
82 /* 16 bit, RGB565 color spanline and pixel functions
83 */
84 #define SPANTMP_PIXEL_FMT GL_RGB
85 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
86
87 #define TAG(x) r128##x##_RGB565
88 #define TAG2(x,y) r128##x##_RGB565##y
89 #define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
90 + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
91 #include "spantmp2.h"
92
93
94 /* 32 bit, ARGB8888 color spanline and pixel functions
95 */
96 #define SPANTMP_PIXEL_FMT GL_BGRA
97 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
98
99 #define TAG(x) r128##x##_ARGB8888
100 #define TAG2(x,y) r128##x##_ARGB8888##y
101 #define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
102 + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
103 #include "spantmp2.h"
104
105 /* Idling in the depth/stencil span functions:
106 * For writes, the kernel reads from the given user-space buffer at dispatch
107 * time, and then writes to the depth buffer asynchronously.
108 * For reads, the kernel reads from the depth buffer and writes to the span
109 * temporary asynchronously.
110 * So, if we're going to read from the span temporary, we need to idle before
111 * doing so. But we don't need to idle after write, because the CPU won't
112 * be accessing the destination, only the accelerator (through 3d rendering or
113 * depth span reads)
114 * However, due to interactions from pixel cache between 2d (what we do with
115 * depth) and 3d (all other parts of the system), we idle at the begin and end
116 * of a set of span operations, which should cover the pix cache issue.
117 * Except, we still have major issues, as shown by no_rast=true glxgears, or
118 * stencilwrap.
119 */
120
121 /* ================================================================
122 * Depth buffer
123 */
124
125 /* These functions require locking */
126 #undef HW_LOCK
127 #undef HW_UNLOCK
128 #define HW_LOCK() LOCK_HARDWARE(R128_CONTEXT(ctx));
129 #define HW_UNLOCK() UNLOCK_HARDWARE(R128_CONTEXT(ctx));
130
131 /* 16-bit depth buffer functions
132 */
133
134 #define WRITE_DEPTH_SPAN() \
135 do { \
136 r128WriteDepthSpanLocked( rmesa, n, \
137 x + dPriv->x, \
138 y + dPriv->y, \
139 depth, mask ); \
140 } while (0)
141
142 #define WRITE_DEPTH_PIXELS() \
143 do { \
144 GLint ox[MAX_WIDTH]; \
145 GLint oy[MAX_WIDTH]; \
146 for ( i = 0 ; i < n ; i++ ) { \
147 ox[i] = x[i] + dPriv->x; \
148 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
149 } \
150 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
151 } while (0)
152
153 #define READ_DEPTH_SPAN() \
154 do { \
155 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
156 r128scrn->spanOffset); \
157 GLint i; \
158 \
159 r128ReadDepthSpanLocked( rmesa, n, \
160 x + dPriv->x, \
161 y + dPriv->y ); \
162 r128WaitForIdleLocked( rmesa ); \
163 \
164 for ( i = 0 ; i < n ; i++ ) { \
165 depth[i] = buf[i]; \
166 } \
167 } while (0)
168
169 #define READ_DEPTH_PIXELS() \
170 do { \
171 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
172 r128scrn->spanOffset); \
173 GLint i, remaining = n; \
174 \
175 while ( remaining > 0 ) { \
176 GLint ox[128]; \
177 GLint oy[128]; \
178 GLint count; \
179 \
180 if ( remaining <= 128 ) { \
181 count = remaining; \
182 } else { \
183 count = 128; \
184 } \
185 for ( i = 0 ; i < count ; i++ ) { \
186 ox[i] = x[i] + dPriv->x; \
187 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
188 } \
189 \
190 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
191 r128WaitForIdleLocked( rmesa ); \
192 \
193 for ( i = 0 ; i < count ; i++ ) { \
194 depth[i] = buf[i]; \
195 } \
196 depth += count; \
197 x += count; \
198 y += count; \
199 remaining -= count; \
200 } \
201 } while (0)
202
203 #define TAG(x) r128##x##_z16
204 #include "depthtmp.h"
205
206
207 /* 24-bit depth, 8-bit stencil buffer functions
208 */
209 #define WRITE_DEPTH_SPAN() \
210 do { \
211 GLuint buf[n]; \
212 GLint i; \
213 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
214 r128scrn->spanOffset); \
215 r128ReadDepthSpanLocked( rmesa, n, \
216 x + dPriv->x, \
217 y + dPriv->y ); \
218 r128WaitForIdleLocked( rmesa ); \
219 for ( i = 0 ; i < n ; i++ ) { \
220 buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
221 } \
222 r128WriteDepthSpanLocked( rmesa, n, \
223 x + dPriv->x, \
224 y + dPriv->y, \
225 buf, mask ); \
226 } while (0)
227
228 #define WRITE_DEPTH_PIXELS() \
229 do { \
230 GLuint buf[n]; \
231 GLint ox[MAX_WIDTH]; \
232 GLint oy[MAX_WIDTH]; \
233 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
234 r128scrn->spanOffset); \
235 for ( i = 0 ; i < n ; i++ ) { \
236 ox[i] = x[i] + dPriv->x; \
237 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
238 } \
239 r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
240 r128WaitForIdleLocked( rmesa ); \
241 for ( i = 0 ; i < n ; i++ ) { \
242 buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
243 } \
244 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
245 } while (0)
246
247 #define READ_DEPTH_SPAN() \
248 do { \
249 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
250 r128scrn->spanOffset); \
251 GLint i; \
252 \
253 /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
254 r128ReadDepthSpanLocked( rmesa, n, \
255 x + dPriv->x, \
256 y + dPriv->y ); \
257 r128WaitForIdleLocked( rmesa ); \
258 \
259 for ( i = 0 ; i < n ; i++ ) { \
260 depth[i] = buf[i] & 0x00ffffff; \
261 } \
262 } while (0)
263
264 #define READ_DEPTH_PIXELS() \
265 do { \
266 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
267 r128scrn->spanOffset); \
268 GLint i, remaining = n; \
269 \
270 while ( remaining > 0 ) { \
271 GLint ox[128]; \
272 GLint oy[128]; \
273 GLint count; \
274 \
275 if ( remaining <= 128 ) { \
276 count = remaining; \
277 } else { \
278 count = 128; \
279 } \
280 for ( i = 0 ; i < count ; i++ ) { \
281 ox[i] = x[i] + dPriv->x; \
282 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
283 } \
284 \
285 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
286 r128WaitForIdleLocked( rmesa ); \
287 \
288 for ( i = 0 ; i < count ; i++ ) { \
289 depth[i] = buf[i] & 0x00ffffff; \
290 } \
291 depth += count; \
292 x += count; \
293 y += count; \
294 remaining -= count; \
295 } \
296 } while (0)
297
298 #define TAG(x) r128##x##_z24_s8
299 #include "depthtmp.h"
300
301
302
303 /* ================================================================
304 * Stencil buffer
305 */
306
307 /* 24 bit depth, 8 bit stencil depthbuffer functions
308 */
309 #define WRITE_STENCIL_SPAN() \
310 do { \
311 GLuint buf[n]; \
312 GLint i; \
313 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
314 r128scrn->spanOffset); \
315 r128ReadDepthSpanLocked( rmesa, n, \
316 x + dPriv->x, \
317 y + dPriv->y ); \
318 r128WaitForIdleLocked( rmesa ); \
319 for ( i = 0 ; i < n ; i++ ) { \
320 buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
321 } \
322 r128WriteDepthSpanLocked( rmesa, n, \
323 x + dPriv->x, \
324 y + dPriv->y, \
325 buf, mask ); \
326 } while (0)
327
328 #define WRITE_STENCIL_PIXELS() \
329 do { \
330 GLuint buf[n]; \
331 GLint ox[MAX_WIDTH]; \
332 GLint oy[MAX_WIDTH]; \
333 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
334 r128scrn->spanOffset); \
335 for ( i = 0 ; i < n ; i++ ) { \
336 ox[i] = x[i] + dPriv->x; \
337 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
338 } \
339 r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
340 r128WaitForIdleLocked( rmesa ); \
341 for ( i = 0 ; i < n ; i++ ) { \
342 buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
343 } \
344 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
345 } while (0)
346
347 #define READ_STENCIL_SPAN() \
348 do { \
349 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
350 r128scrn->spanOffset); \
351 GLint i; \
352 \
353 /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
354 r128ReadDepthSpanLocked( rmesa, n, \
355 x + dPriv->x, \
356 y + dPriv->y ); \
357 r128WaitForIdleLocked( rmesa ); \
358 \
359 for ( i = 0 ; i < n ; i++ ) { \
360 stencil[i] = (buf[i] & 0xff000000) >> 24; \
361 } \
362 } while (0)
363
364 #define READ_STENCIL_PIXELS() \
365 do { \
366 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
367 r128scrn->spanOffset); \
368 GLint i, remaining = n; \
369 \
370 while ( remaining > 0 ) { \
371 GLint ox[128]; \
372 GLint oy[128]; \
373 GLint count; \
374 \
375 if ( remaining <= 128 ) { \
376 count = remaining; \
377 } else { \
378 count = 128; \
379 } \
380 for ( i = 0 ; i < count ; i++ ) { \
381 ox[i] = x[i] + dPriv->x; \
382 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
383 } \
384 \
385 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
386 r128WaitForIdleLocked( rmesa ); \
387 \
388 for ( i = 0 ; i < count ; i++ ) { \
389 stencil[i] = (buf[i] & 0xff000000) >> 24; \
390 } \
391 stencil += count; \
392 x += count; \
393 y += count; \
394 remaining -= count; \
395 } \
396 } while (0)
397
398 #define TAG(x) radeon##x##_z24_s8
399 #include "stenciltmp.h"
400
401 static void
402 r128SpanRenderStart( GLcontext *ctx )
403 {
404 r128ContextPtr rmesa = R128_CONTEXT(ctx);
405 FLUSH_BATCH(rmesa);
406 LOCK_HARDWARE(rmesa);
407 r128WaitForIdleLocked( rmesa );
408 }
409
410 static void
411 r128SpanRenderFinish( GLcontext *ctx )
412 {
413 r128ContextPtr rmesa = R128_CONTEXT(ctx);
414 _swrast_flush( ctx );
415 r128WaitForIdleLocked( rmesa );
416 UNLOCK_HARDWARE( rmesa );
417 }
418
419 void r128DDInitSpanFuncs( GLcontext *ctx )
420 {
421 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
422 swdd->SpanRenderStart = r128SpanRenderStart;
423 swdd->SpanRenderFinish = r128SpanRenderFinish;
424 }
425
426
427 /**
428 * Plug in the Get/Put routines for the given driRenderbuffer.
429 */
430 void
431 r128SetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
432 {
433 if (drb->Base.InternalFormat == GL_RGBA) {
434 if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
435 r128InitPointers_RGB565(&drb->Base);
436 }
437 else {
438 r128InitPointers_ARGB8888(&drb->Base);
439 }
440 }
441 else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
442 r128InitDepthPointers_z16(&drb->Base);
443 }
444 else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
445 r128InitDepthPointers_z24_s8(&drb->Base);
446 }
447 else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
448 radeonInitStencilPointers_z24_s8(&drb->Base);
449 }
450 }