Attempt to fix the issue reported by Alan Grimes with DRM_RADEON_TEXTURE
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_span.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.c,v 1.6 2002/10/30 12:51:56 alanh Exp $ */
2 /**************************************************************************
3
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
6
7 All Rights Reserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Kevin E. Martin <martin@valinux.com>
34 * Gareth Hughes <gareth@valinux.com>
35 * Keith Whitwell <keith@tungstengraphics.com>
36 *
37 */
38
39 #include "glheader.h"
40 #include "swrast/swrast.h"
41
42 #include "radeon_context.h"
43 #include "radeon_ioctl.h"
44 #include "radeon_state.h"
45 #include "radeon_span.h"
46 #include "radeon_tex.h"
47
48 #define DBG 0
49
50 #define LOCAL_VARS \
51 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
52 radeonScreenPtr radeonScreen = rmesa->radeonScreen; \
53 __DRIscreenPrivate *sPriv = rmesa->dri.screen; \
54 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
55 GLuint pitch = radeonScreen->frontPitch * radeonScreen->cpp; \
56 GLuint height = dPriv->h; \
57 char *buf = (char *)(sPriv->pFB + \
58 rmesa->state.color.drawOffset + \
59 (dPriv->x * radeonScreen->cpp) + \
60 (dPriv->y * pitch)); \
61 char *read_buf = (char *)(sPriv->pFB + \
62 rmesa->state.pixel.readOffset + \
63 (dPriv->x * radeonScreen->cpp) + \
64 (dPriv->y * pitch)); \
65 GLuint p; \
66 (void) read_buf; (void) buf; (void) p
67
68 #define LOCAL_DEPTH_VARS \
69 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
70 radeonScreenPtr radeonScreen = rmesa->radeonScreen; \
71 __DRIscreenPrivate *sPriv = rmesa->dri.screen; \
72 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \
73 GLuint height = dPriv->h; \
74 GLuint xo = dPriv->x; \
75 GLuint yo = dPriv->y; \
76 char *buf = (char *)(sPriv->pFB + radeonScreen->depthOffset); \
77 (void) buf
78
79 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
80
81 #define Y_FLIP( _y ) (height - _y - 1)
82
83 #define HW_LOCK()
84
85 #define HW_UNLOCK()
86
87
88
89 /* ================================================================
90 * Color buffer
91 */
92
93 /* 16 bit, RGB565 color spanline and pixel functions
94 */
95 #define SPANTMP_PIXEL_FMT GL_RGB
96 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
97
98 #define TAG(x) radeon##x##_RGB565
99 #define TAG2(x,y) radeon##x##_RGB565##y
100 #include "spantmp2.h"
101
102 /* 32 bit, ARGB8888 color spanline and pixel functions
103 */
104 #define SPANTMP_PIXEL_FMT GL_BGRA
105 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
106
107 #define TAG(x) radeon##x##_ARGB8888
108 #define TAG2(x,y) radeon##x##_ARGB8888##y
109 #include "spantmp2.h"
110
111
112 /* ================================================================
113 * Depth buffer
114 */
115
116 /* The Radeon family has depth tiling on all the time, so we have to convert
117 * the x,y coordinates into the memory bus address (mba) in the same
118 * manner as the engine. In each case, the linear block address (ba)
119 * is calculated, and then wired with x and y to produce the final
120 * memory address.
121 * The chip will do address translation on its own if the surface registers
122 * are set up correctly. It is not quite enough to get it working with hyperz too...
123 */
124
125 static GLuint radeon_mba_z32( radeonContextPtr rmesa,
126 GLint x, GLint y )
127 {
128 GLuint pitch = rmesa->radeonScreen->frontPitch;
129 if (rmesa->radeonScreen->depthHasSurface) {
130 return 4*(x + y*pitch);
131 }
132 else {
133 GLuint ba, address = 0; /* a[0..1] = 0 */
134
135 ba = (y / 16) * (pitch / 16) + (x / 16);
136
137 address |= (x & 0x7) << 2; /* a[2..4] = x[0..2] */
138 address |= (y & 0x3) << 5; /* a[5..6] = y[0..1] */
139 address |=
140 (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; /* a[7] = x[4] ^ y[2] */
141 address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
142
143 address |= (y & 0x8) << 7; /* a[10] = y[3] */
144 address |=
145 (((x & 0x8) << 1) ^ (y & 0x10)) << 7; /* a[11] = x[3] ^ y[4] */
146 address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
147
148 return address;
149 }
150 }
151
152 static __inline GLuint radeon_mba_z16( radeonContextPtr rmesa, GLint x, GLint y )
153 {
154 GLuint pitch = rmesa->radeonScreen->frontPitch;
155 if (rmesa->radeonScreen->depthHasSurface) {
156 return 2*(x + y*pitch);
157 }
158 else {
159 GLuint ba, address = 0; /* a[0] = 0 */
160
161 ba = (y / 16) * (pitch / 32) + (x / 32);
162
163 address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */
164 address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */
165 address |= (x & 0x8) << 4; /* a[7] = x[3] */
166 address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
167 address |= (y & 0x8) << 7; /* a[10] = y[3] */
168 address |= ((x & 0x10) ^ (y & 0x10)) << 7; /* a[11] = x[4] ^ y[4] */
169 address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
170
171 return address;
172 }
173 }
174
175
176 /* 16-bit depth buffer functions
177 */
178 #define WRITE_DEPTH( _x, _y, d ) \
179 *(GLushort *)(buf + radeon_mba_z16( rmesa, _x + xo, _y + yo )) = d;
180
181 #define READ_DEPTH( d, _x, _y ) \
182 d = *(GLushort *)(buf + radeon_mba_z16( rmesa, _x + xo, _y + yo ));
183
184 #define TAG(x) radeon##x##_16
185 #include "depthtmp.h"
186
187 /* 24 bit depth, 8 bit stencil depthbuffer functions
188 */
189 #define WRITE_DEPTH( _x, _y, d ) \
190 do { \
191 GLuint offset = radeon_mba_z32( rmesa, _x + xo, _y + yo ); \
192 GLuint tmp = *(GLuint *)(buf + offset); \
193 tmp &= 0xff000000; \
194 tmp |= ((d) & 0x00ffffff); \
195 *(GLuint *)(buf + offset) = tmp; \
196 } while (0)
197
198 #define READ_DEPTH( d, _x, _y ) \
199 d = *(GLuint *)(buf + radeon_mba_z32( rmesa, _x + xo, \
200 _y + yo )) & 0x00ffffff;
201
202 #define TAG(x) radeon##x##_24_8
203 #include "depthtmp.h"
204
205
206 /* ================================================================
207 * Stencil buffer
208 */
209
210 /* 24 bit depth, 8 bit stencil depthbuffer functions
211 */
212 #define WRITE_STENCIL( _x, _y, d ) \
213 do { \
214 GLuint offset = radeon_mba_z32( rmesa, _x + xo, _y + yo ); \
215 GLuint tmp = *(GLuint *)(buf + offset); \
216 tmp &= 0x00ffffff; \
217 tmp |= (((d) & 0xff) << 24); \
218 *(GLuint *)(buf + offset) = tmp; \
219 } while (0)
220
221 #define READ_STENCIL( d, _x, _y ) \
222 do { \
223 GLuint offset = radeon_mba_z32( rmesa, _x + xo, _y + yo ); \
224 GLuint tmp = *(GLuint *)(buf + offset); \
225 tmp &= 0xff000000; \
226 d = tmp >> 24; \
227 } while (0)
228
229 #define TAG(x) radeon##x##_24_8
230 #include "stenciltmp.h"
231
232
233 /*
234 * This function is called to specify which buffer to read and write
235 * for software rasterization (swrast) fallbacks. This doesn't necessarily
236 * correspond to glDrawBuffer() or glReadBuffer() calls.
237 */
238 static void radeonSetBuffer( GLcontext *ctx,
239 GLframebuffer *colorBuffer,
240 GLuint bufferBit )
241 {
242 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
243
244 switch ( bufferBit ) {
245 case BUFFER_BIT_FRONT_LEFT:
246 if ( rmesa->sarea->pfCurrentPage == 1 ) {
247 rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset;
248 rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch;
249 rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
250 rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
251 } else {
252 rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset;
253 rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch;
254 rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
255 rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
256 }
257 break;
258 case BUFFER_BIT_BACK_LEFT:
259 if ( rmesa->sarea->pfCurrentPage == 1 ) {
260 rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset;
261 rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch;
262 rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
263 rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
264 } else {
265 rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset;
266 rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch;
267 rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
268 rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
269 }
270 break;
271 default:
272 assert(0);
273 break;
274 }
275 }
276
277 /* Move locking out to get reasonable span performance (10x better
278 * than doing this in HW_LOCK above). WaitForIdle() is the main
279 * culprit.
280 */
281
282 static void radeonSpanRenderStart( GLcontext *ctx )
283 {
284 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
285
286 RADEON_FIREVERTICES( rmesa );
287 LOCK_HARDWARE( rmesa );
288 radeonWaitForIdleLocked( rmesa );
289 }
290
291 static void radeonSpanRenderFinish( GLcontext *ctx )
292 {
293 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
294 _swrast_flush( ctx );
295 UNLOCK_HARDWARE( rmesa );
296 }
297
298 void radeonInitSpanFuncs( GLcontext *ctx )
299 {
300 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
301
302 swdd->SetBuffer = radeonSetBuffer;
303 swdd->SpanRenderStart = radeonSpanRenderStart;
304 swdd->SpanRenderFinish = radeonSpanRenderFinish;
305 }
306
307
308 /**
309 * Plug in the Get/Put routines for the given driRenderbuffer.
310 */
311 void
312 radeonSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
313 {
314 if (drb->Base.InternalFormat == GL_RGBA) {
315 if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
316 radeonInitPointers_RGB565(&drb->Base);
317 }
318 else {
319 radeonInitPointers_ARGB8888(&drb->Base);
320 }
321 }
322 else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
323 drb->Base.GetRow = radeonReadDepthSpan_16;
324 drb->Base.GetValues = radeonReadDepthPixels_16;
325 drb->Base.PutRow = radeonWriteDepthSpan_16;
326 drb->Base.PutMonoRow = radeonWriteMonoDepthSpan_16;
327 drb->Base.PutValues = radeonWriteDepthPixels_16;
328 drb->Base.PutMonoValues = NULL;
329 }
330 else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
331 drb->Base.GetRow = radeonReadDepthSpan_24_8;
332 drb->Base.GetValues = radeonReadDepthPixels_24_8;
333 drb->Base.PutRow = radeonWriteDepthSpan_24_8;
334 drb->Base.PutMonoRow = radeonWriteMonoDepthSpan_24_8;
335 drb->Base.PutValues = radeonWriteDepthPixels_24_8;
336 drb->Base.PutMonoValues = NULL;
337 }
338 else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
339 drb->Base.GetRow = radeonReadStencilSpan_24_8;
340 drb->Base.GetValues = radeonReadStencilPixels_24_8;
341 drb->Base.PutRow = radeonWriteStencilSpan_24_8;
342 drb->Base.PutMonoRow = radeonWriteMonoStencilSpan_24_8;
343 drb->Base.PutValues = radeonWriteStencilPixels_24_8;
344 drb->Base.PutMonoValues = NULL;
345 }
346 }