1 /**************************************************************************
3 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
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:
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
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.
26 **************************************************************************/
30 * Gareth Hughes <gareth@valinux.com>
31 * Keith Whitwell <keith@tungstengraphics.com>
32 * Kevin E. Martin <martin@valinux.com>
36 #include "r128_context.h"
37 #include "r128_ioctl.h"
38 #include "r128_span.h"
40 #include "swrast/swrast.h"
44 #define HAVE_HW_DEPTH_SPANS 1
45 #define HAVE_HW_DEPTH_PIXELS 1
46 #define HAVE_HW_STENCIL_SPANS 1
47 #define HAVE_HW_STENCIL_PIXELS 1
50 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
51 __DRIscreen *sPriv = rmesa->driScreen; \
52 __DRIdrawable *dPriv = rmesa->driDrawable; \
53 driRenderbuffer *drb = (driRenderbuffer *) rb; \
54 GLuint height = dPriv->h; \
58 #define LOCAL_DEPTH_VARS \
59 r128ContextPtr rmesa = R128_CONTEXT(ctx); \
60 r128ScreenPtr r128scrn = rmesa->r128Screen; \
61 __DRIscreen *sPriv = rmesa->driScreen; \
62 __DRIdrawable *dPriv = rmesa->driDrawable; \
63 GLuint height = dPriv->h; \
64 (void) r128scrn; (void) sPriv; (void) height
66 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
68 #define Y_FLIP( _y ) (height - _y - 1)
76 /* ================================================================
80 /* 16 bit, RGB565 color spanline and pixel functions
82 #define SPANTMP_PIXEL_FMT GL_RGB
83 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
85 #define TAG(x) r128##x##_RGB565
86 #define TAG2(x,y) r128##x##_RGB565##y
87 #define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
88 + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
92 /* 32 bit, ARGB8888 color spanline and pixel functions
94 #define SPANTMP_PIXEL_FMT GL_BGRA
95 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
97 #define TAG(x) r128##x##_ARGB8888
98 #define TAG2(x,y) r128##x##_ARGB8888##y
99 #define GET_PTR(X,Y) (sPriv->pFB + drb->flippedOffset \
100 + ((dPriv->y + (Y)) * drb->flippedPitch + (dPriv->x + (X))) * drb->cpp)
101 #include "spantmp2.h"
103 /* Idling in the depth/stencil span functions:
104 * For writes, the kernel reads from the given user-space buffer at dispatch
105 * time, and then writes to the depth buffer asynchronously.
106 * For reads, the kernel reads from the depth buffer and writes to the span
107 * temporary asynchronously.
108 * So, if we're going to read from the span temporary, we need to idle before
109 * doing so. But we don't need to idle after write, because the CPU won't
110 * be accessing the destination, only the accelerator (through 3d rendering or
112 * However, due to interactions from pixel cache between 2d (what we do with
113 * depth) and 3d (all other parts of the system), we idle at the begin and end
114 * of a set of span operations, which should cover the pix cache issue.
115 * Except, we still have major issues, as shown by no_rast=true glxgears, or
119 /* ================================================================
123 /* These functions require locking */
126 #define HW_LOCK() LOCK_HARDWARE(R128_CONTEXT(ctx));
127 #define HW_UNLOCK() UNLOCK_HARDWARE(R128_CONTEXT(ctx));
129 /* 16-bit depth buffer functions
131 #define VALUE_TYPE GLushort
133 #define WRITE_DEPTH_SPAN() \
135 r128WriteDepthSpanLocked( rmesa, n, \
141 #define WRITE_DEPTH_PIXELS() \
143 GLint ox[MAX_WIDTH]; \
144 GLint oy[MAX_WIDTH]; \
145 for ( i = 0 ; i < n ; i++ ) { \
146 ox[i] = x[i] + dPriv->x; \
147 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
149 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
152 #define READ_DEPTH_SPAN() \
154 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
155 r128scrn->spanOffset); \
158 r128ReadDepthSpanLocked( rmesa, n, \
161 r128WaitForIdleLocked( rmesa ); \
163 for ( i = 0 ; i < n ; i++ ) { \
168 #define READ_DEPTH_PIXELS() \
170 GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
171 r128scrn->spanOffset); \
172 GLint i, remaining = n; \
174 while ( remaining > 0 ) { \
179 if ( remaining <= 128 ) { \
184 for ( i = 0 ; i < count ; i++ ) { \
185 ox[i] = x[i] + dPriv->x; \
186 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
189 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
190 r128WaitForIdleLocked( rmesa ); \
192 for ( i = 0 ; i < count ; i++ ) { \
198 remaining -= count; \
202 #define TAG(x) r128##x##_z16
203 #include "depthtmp.h"
206 /* 24-bit depth, 8-bit stencil buffer functions
208 #define VALUE_TYPE GLuint
210 #define WRITE_DEPTH_SPAN() \
214 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
215 r128scrn->spanOffset); \
216 r128ReadDepthSpanLocked( rmesa, n, \
219 r128WaitForIdleLocked( rmesa ); \
220 for ( i = 0 ; i < n ; i++ ) { \
221 buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
223 r128WriteDepthSpanLocked( rmesa, n, \
229 #define WRITE_DEPTH_PIXELS() \
232 GLint ox[MAX_WIDTH]; \
233 GLint oy[MAX_WIDTH]; \
234 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
235 r128scrn->spanOffset); \
236 for ( i = 0 ; i < n ; i++ ) { \
237 ox[i] = x[i] + dPriv->x; \
238 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
240 r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
241 r128WaitForIdleLocked( rmesa ); \
242 for ( i = 0 ; i < n ; i++ ) { \
243 buf[i] = (readbuf[i] & 0xff000000) | (depth[i] & 0x00ffffff); \
245 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
248 #define READ_DEPTH_SPAN() \
250 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
251 r128scrn->spanOffset); \
254 /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
255 r128ReadDepthSpanLocked( rmesa, n, \
258 r128WaitForIdleLocked( rmesa ); \
260 for ( i = 0 ; i < n ; i++ ) { \
261 depth[i] = buf[i] & 0x00ffffff; \
265 #define READ_DEPTH_PIXELS() \
267 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
268 r128scrn->spanOffset); \
269 GLint i, remaining = n; \
271 while ( remaining > 0 ) { \
276 if ( remaining <= 128 ) { \
281 for ( i = 0 ; i < count ; i++ ) { \
282 ox[i] = x[i] + dPriv->x; \
283 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
286 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
287 r128WaitForIdleLocked( rmesa ); \
289 for ( i = 0 ; i < count ; i++ ) { \
290 depth[i] = buf[i] & 0x00ffffff; \
295 remaining -= count; \
299 #define TAG(x) r128##x##_z24_s8
300 #include "depthtmp.h"
304 /* ================================================================
308 /* 24 bit depth, 8 bit stencil depthbuffer functions
310 #define WRITE_STENCIL_SPAN() \
314 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
315 r128scrn->spanOffset); \
316 r128ReadDepthSpanLocked( rmesa, n, \
319 r128WaitForIdleLocked( rmesa ); \
320 for ( i = 0 ; i < n ; i++ ) { \
321 buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
323 r128WriteDepthSpanLocked( rmesa, n, \
329 #define WRITE_STENCIL_PIXELS() \
332 GLint ox[MAX_WIDTH]; \
333 GLint oy[MAX_WIDTH]; \
334 GLuint *readbuf = (GLuint *)((GLubyte *)sPriv->pFB + \
335 r128scrn->spanOffset); \
336 for ( i = 0 ; i < n ; i++ ) { \
337 ox[i] = x[i] + dPriv->x; \
338 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
340 r128ReadDepthPixelsLocked( rmesa, n, ox, oy ); \
341 r128WaitForIdleLocked( rmesa ); \
342 for ( i = 0 ; i < n ; i++ ) { \
343 buf[i] = (readbuf[i] & 0x00ffffff) | (stencil[i] << 24); \
345 r128WriteDepthPixelsLocked( rmesa, n, ox, oy, buf, mask ); \
348 #define READ_STENCIL_SPAN() \
350 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
351 r128scrn->spanOffset); \
354 /*if (n >= 128) fprintf(stderr, "Large number of pixels: %d\n", n);*/ \
355 r128ReadDepthSpanLocked( rmesa, n, \
358 r128WaitForIdleLocked( rmesa ); \
360 for ( i = 0 ; i < n ; i++ ) { \
361 stencil[i] = (buf[i] & 0xff000000) >> 24; \
365 #define READ_STENCIL_PIXELS() \
367 GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
368 r128scrn->spanOffset); \
369 GLint i, remaining = n; \
371 while ( remaining > 0 ) { \
376 if ( remaining <= 128 ) { \
381 for ( i = 0 ; i < count ; i++ ) { \
382 ox[i] = x[i] + dPriv->x; \
383 oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
386 r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
387 r128WaitForIdleLocked( rmesa ); \
389 for ( i = 0 ; i < count ; i++ ) { \
390 stencil[i] = (buf[i] & 0xff000000) >> 24; \
395 remaining -= count; \
399 #define TAG(x) radeon##x##_z24_s8
400 #include "stenciltmp.h"
403 r128SpanRenderStart( GLcontext
*ctx
)
405 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
407 LOCK_HARDWARE(rmesa
);
408 r128WaitForIdleLocked( rmesa
);
412 r128SpanRenderFinish( GLcontext
*ctx
)
414 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
415 _swrast_flush( ctx
);
416 r128WaitForIdleLocked( rmesa
);
417 UNLOCK_HARDWARE( rmesa
);
420 void r128DDInitSpanFuncs( GLcontext
*ctx
)
422 struct swrast_device_driver
*swdd
= _swrast_GetDeviceDriverReference(ctx
);
423 swdd
->SpanRenderStart
= r128SpanRenderStart
;
424 swdd
->SpanRenderFinish
= r128SpanRenderFinish
;
429 * Plug in the Get/Put routines for the given driRenderbuffer.
432 r128SetSpanFunctions(driRenderbuffer
*drb
, const GLvisual
*vis
)
434 if (drb
->Base
.Format
== MESA_FORMAT_RGB565
) {
435 r128InitPointers_RGB565(&drb
->Base
);
437 else if (drb
->Base
.Format
== MESA_FORMAT_ARGB8888
) {
438 r128InitPointers_ARGB8888(&drb
->Base
);
440 else if (drb
->Base
.Format
== MESA_FORMAT_Z16
) {
441 r128InitDepthPointers_z16(&drb
->Base
);
443 else if (drb
->Base
.Format
== MESA_FORMAT_S8_Z24
) {
444 r128InitDepthPointers_z24_s8(&drb
->Base
);
446 else if (drb
->Base
.Format
== MESA_FORMAT_S8
) {
447 radeonInitStencilPointers_z24_s8(&drb
->Base
);