(Stephane Marchesin, me) add hyperz support to radeon and r200 drivers. Only fast...
[mesa.git] / src / mesa / drivers / dri / i830 / i830_span.c
1 /**************************************************************************
2
3 Copyright 2001 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 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, VA LINUX SYSTEMS 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 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_span.c,v 1.4 2002/12/10 01:26:53 dawes Exp $ */
29
30 /**
31 * \file i830_span.c
32 *
33 * Heavily based on the I810 driver, which was written by Keith Whitwell.
34 *
35 * \author Jeff Hartmann <jhartmann@2d3d.com>
36 * \author Keith Whitwell <keith@tungstengraphics.com>
37 */
38
39 #include "glheader.h"
40 #include "macros.h"
41 #include "mtypes.h"
42 #include "colormac.h"
43
44 #include "i830_screen.h"
45 #include "i830_dri.h"
46
47 #include "i830_span.h"
48 #include "i830_ioctl.h"
49 #include "swrast/swrast.h"
50
51
52 #define DBG 0
53
54 #define LOCAL_VARS \
55 i830ContextPtr imesa = I830_CONTEXT(ctx); \
56 __DRIdrawablePrivate *dPriv = imesa->mesa_drawable; \
57 i830ScreenPrivate *i830Screen = imesa->i830Screen; \
58 GLuint pitch = i830Screen->backPitch * i830Screen->cpp; \
59 GLuint height = dPriv->h; \
60 char *buf = (char *)(imesa->drawMap + \
61 dPriv->x * i830Screen->cpp + \
62 dPriv->y * pitch); \
63 char *read_buf = (char *)(imesa->readMap + \
64 dPriv->x * i830Screen->cpp + \
65 dPriv->y * pitch); \
66 GLushort p; \
67 (void) read_buf; (void) buf; (void) p
68
69 #define LOCAL_DEPTH_VARS \
70 i830ContextPtr imesa = I830_CONTEXT(ctx); \
71 __DRIdrawablePrivate *dPriv = imesa->mesa_drawable; \
72 i830ScreenPrivate *i830Screen = imesa->i830Screen; \
73 GLuint pitch = i830Screen->backPitch * i830Screen->cpp; \
74 GLuint height = dPriv->h; \
75 char *buf = (char *)(i830Screen->depth.map + \
76 dPriv->x * i830Screen->cpp + \
77 dPriv->y * pitch)
78
79 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
80
81 #define INIT_MONO_PIXEL(p,color)\
82 p = PACK_COLOR_565(color[0],color[1],color[2])
83
84 #define CLIPPIXEL(_x,_y) (_x >= minx && _x < maxx && \
85 _y >= miny && _y < maxy)
86
87 #define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
88 if ( _y < miny || _y >= maxy ) { \
89 _n1 = 0, _x1 = x; \
90 } else { \
91 _n1 = _n; \
92 _x1 = _x; \
93 if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
94 if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
95 }
96
97 #define Y_FLIP(_y) (height - _y - 1)
98
99
100 #define HW_LOCK()
101
102 #define HW_CLIPLOOP() \
103 do { \
104 __DRIdrawablePrivate *dPriv = imesa->driDrawable; \
105 int _nc = dPriv->numClipRects; \
106 while (_nc--) { \
107 int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
108 int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
109 int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
110 int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
111
112
113 #define HW_ENDCLIPLOOP() \
114 } \
115 } while (0)
116
117 #define HW_UNLOCK()
118
119 /* 16 bit, 565 rgb color spanline and pixel functions
120 */
121 #define WRITE_RGBA( _x, _y, r, g, b, a ) \
122 *(GLushort *)(buf + _x*2 + _y*pitch) = ( (((int)r & 0xf8) << 8) | \
123 (((int)g & 0xfc) << 3) | \
124 (((int)b & 0xf8) >> 3))
125 #define WRITE_PIXEL( _x, _y, p ) \
126 *(GLushort *)(buf + _x*2 + _y*pitch) = p
127
128 #define READ_RGBA( rgba, _x, _y ) \
129 do { \
130 GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \
131 rgba[0] = (((p >> 11) & 0x1f) * 255) / 31; \
132 rgba[1] = (((p >> 5) & 0x3f) * 255) / 63; \
133 rgba[2] = (((p >> 0) & 0x1f) * 255) / 31; \
134 rgba[3] = 255; \
135 } while(0)
136
137 #define TAG(x) i830##x##_565
138 #include "spantmp.h"
139
140
141
142
143 /* 15 bit, 555 rgb color spanline and pixel functions
144 */
145 #define WRITE_RGBA( _x, _y, r, g, b, a ) \
146 *(GLushort *)(buf + _x*2 + _y*pitch) = (((r & 0xf8) << 7) | \
147 ((g & 0xf8) << 3) | \
148 ((b & 0xf8) >> 3))
149
150 #define WRITE_PIXEL( _x, _y, p ) \
151 *(GLushort *)(buf + _x*2 + _y*pitch) = p
152
153 #define READ_RGBA( rgba, _x, _y ) \
154 do { \
155 GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \
156 rgba[0] = (p >> 7) & 0xf8; \
157 rgba[1] = (p >> 3) & 0xf8; \
158 rgba[2] = (p << 3) & 0xf8; \
159 rgba[3] = 255; \
160 } while(0)
161
162 #define TAG(x) i830##x##_555
163 #include "spantmp.h"
164
165 /* 16 bit depthbuffer functions.
166 */
167 #define WRITE_DEPTH( _x, _y, d ) \
168 *(GLushort *)(buf + _x*2 + _y*pitch) = d;
169
170 #define READ_DEPTH( d, _x, _y ) \
171 d = *(GLushort *)(buf + _x*2 + _y*pitch);
172
173
174 #define TAG(x) i830##x##_16
175 #include "depthtmp.h"
176
177
178 #undef LOCAL_VARS
179 #define LOCAL_VARS \
180 i830ContextPtr imesa = I830_CONTEXT(ctx); \
181 __DRIdrawablePrivate *dPriv = imesa->driDrawable; \
182 i830ScreenPrivate *i830Screen = imesa->i830Screen; \
183 GLuint pitch = i830Screen->backPitch * i830Screen->cpp; \
184 GLuint height = dPriv->h; \
185 char *buf = (char *)(imesa->drawMap + \
186 dPriv->x * i830Screen->cpp + \
187 dPriv->y * pitch); \
188 char *read_buf = (char *)(imesa->readMap + \
189 dPriv->x * i830Screen->cpp + \
190 dPriv->y * pitch); \
191 GLuint p = I830_CONTEXT( ctx )->MonoColor; \
192 (void) read_buf; (void) buf; (void) p
193
194 #undef INIT_MONO_PIXEL
195 #define INIT_MONO_PIXEL(p,color)\
196 p = PACK_COLOR_888(color[0],color[1],color[2])
197
198 /* 32 bit, 8888 argb color spanline and pixel functions
199 */
200 #define WRITE_RGBA(_x, _y, r, g, b, a) \
201 *(GLuint *)(buf + _x*4 + _y*pitch) = ((r << 16) | \
202 (g << 8) | \
203 (b << 0) | \
204 (a << 24) )
205
206 #define WRITE_PIXEL(_x, _y, p) \
207 *(GLuint *)(buf + _x*4 + _y*pitch) = p
208
209
210 #define READ_RGBA(rgba, _x, _y) \
211 do { \
212 GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch); \
213 rgba[0] = (p >> 16) & 0xff; \
214 rgba[1] = (p >> 8) & 0xff; \
215 rgba[2] = (p >> 0) & 0xff; \
216 rgba[3] = (p >> 24) & 0xff; \
217 } while (0)
218
219 #define TAG(x) i830##x##_8888
220 #include "spantmp.h"
221
222 /* 24 bit depthbuffer functions.
223 */
224 #define WRITE_DEPTH( _x, _y, d ) \
225 *(GLuint *)(buf + _x*4 + _y*pitch) = 0xffffff & d;
226
227 #define READ_DEPTH( d, _x, _y ) \
228 d = *(GLuint *)(buf + _x*4 + _y*pitch) & 0xffffff;
229
230 #define TAG(x) i830##x##_24
231 #include "depthtmp.h"
232
233 /* 24/8 bit interleaved depth/stencil functions
234 */
235 #define WRITE_DEPTH( _x, _y, d ) { \
236 GLuint tmp = *(GLuint *)(buf + _x*4 + _y*pitch); \
237 tmp &= 0xff000000; \
238 tmp |= (d) & 0xffffff; \
239 *(GLuint *)(buf + _x*4 + _y*pitch) = tmp; \
240 }
241
242 #define READ_DEPTH( d, _x, _y ) \
243 d = *(GLuint *)(buf + _x*4 + _y*pitch) & 0xffffff;
244
245
246 #define TAG(x) i830##x##_24_8
247 #include "depthtmp.h"
248
249 #define WRITE_STENCIL( _x, _y, d ) { \
250 GLuint tmp = *(GLuint *)(buf + _x*4 + _y*pitch); \
251 tmp &= 0xffffff; \
252 tmp |= (d<<24); \
253 *(GLuint *)(buf + _x*4 + _y*pitch) = tmp; \
254 }
255
256 #define READ_STENCIL( d, _x, _y ) \
257 d = *(GLuint *)(buf + _x*4 + _y*pitch) >> 24;
258
259 #define TAG(x) i830##x##_24_8
260 #include "stenciltmp.h"
261
262 /*
263 * This function is called to specify which buffer to read and write
264 * for software rasterization (swrast) fallbacks. This doesn't necessarily
265 * correspond to glDrawBuffer() or glReadBuffer() calls.
266 */
267 static void i830SetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer,
268 GLuint bufferBit)
269 {
270 i830ContextPtr imesa = I830_CONTEXT(ctx);
271
272 assert( (colorBuffer == imesa->driDrawable->driverPrivate)
273 || (colorBuffer == imesa->driReadable->driverPrivate) );
274
275 imesa->mesa_drawable = (colorBuffer == imesa->driDrawable->driverPrivate)
276 ? imesa->driDrawable : imesa->driReadable;
277
278 if (bufferBit == DD_FRONT_LEFT_BIT) {
279 imesa->drawMap = (char *)imesa->driScreen->pFB;
280 imesa->readMap = (char *)imesa->driScreen->pFB;
281 } else if (bufferBit == DD_BACK_LEFT_BIT) {
282 imesa->drawMap = imesa->i830Screen->back.map;
283 imesa->readMap = imesa->i830Screen->back.map;
284 } else {
285 ASSERT(0);
286 }
287 }
288
289
290
291 /* Move locking out to get reasonable span performance.
292 */
293 void i830SpanRenderStart( GLcontext *ctx )
294 {
295 i830ContextPtr imesa = I830_CONTEXT(ctx);
296 I830_FIREVERTICES(imesa);
297 LOCK_HARDWARE(imesa);
298 i830RegetLockQuiescent( imesa );
299 }
300
301 void i830SpanRenderFinish( GLcontext *ctx )
302 {
303 i830ContextPtr imesa = I830_CONTEXT( ctx );
304 _swrast_flush( ctx );
305 UNLOCK_HARDWARE( imesa );
306 }
307
308 void i830DDInitSpanFuncs( GLcontext *ctx )
309 {
310 i830ContextPtr imesa = I830_CONTEXT(ctx);
311 i830ScreenPrivate *i830Screen = imesa->i830Screen;
312
313 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
314
315 swdd->SetBuffer = i830SetBuffer;
316
317 switch (i830Screen->fbFormat) {
318 case DV_PF_555:
319 swdd->WriteRGBASpan = i830WriteRGBASpan_555;
320 swdd->WriteRGBSpan = i830WriteRGBSpan_555;
321 swdd->WriteMonoRGBASpan = i830WriteMonoRGBASpan_555;
322 swdd->WriteRGBAPixels = i830WriteRGBAPixels_555;
323 swdd->WriteMonoRGBAPixels = i830WriteMonoRGBAPixels_555;
324 swdd->ReadRGBASpan = i830ReadRGBASpan_555;
325 swdd->ReadRGBAPixels = i830ReadRGBAPixels_555;
326
327 swdd->ReadDepthSpan = i830ReadDepthSpan_16;
328 swdd->WriteDepthSpan = i830WriteDepthSpan_16;
329 swdd->ReadDepthPixels = i830ReadDepthPixels_16;
330 swdd->WriteDepthPixels = i830WriteDepthPixels_16;
331 break;
332
333 case DV_PF_565:
334 swdd->WriteRGBASpan = i830WriteRGBASpan_565;
335 swdd->WriteRGBSpan = i830WriteRGBSpan_565;
336 swdd->WriteMonoRGBASpan = i830WriteMonoRGBASpan_565;
337 swdd->WriteRGBAPixels = i830WriteRGBAPixels_565;
338 swdd->WriteMonoRGBAPixels = i830WriteMonoRGBAPixels_565;
339 swdd->ReadRGBASpan = i830ReadRGBASpan_565;
340 swdd->ReadRGBAPixels = i830ReadRGBAPixels_565;
341
342 swdd->ReadDepthSpan = i830ReadDepthSpan_16;
343 swdd->WriteDepthSpan = i830WriteDepthSpan_16;
344 swdd->ReadDepthPixels = i830ReadDepthPixels_16;
345 swdd->WriteDepthPixels = i830WriteDepthPixels_16;
346 break;
347
348 case DV_PF_8888:
349 swdd->WriteRGBASpan = i830WriteRGBASpan_8888;
350 swdd->WriteRGBSpan = i830WriteRGBSpan_8888;
351 swdd->WriteMonoRGBASpan = i830WriteMonoRGBASpan_8888;
352 swdd->WriteRGBAPixels = i830WriteRGBAPixels_8888;
353 swdd->WriteMonoRGBAPixels = i830WriteMonoRGBAPixels_8888;
354 swdd->ReadRGBASpan = i830ReadRGBASpan_8888;
355 swdd->ReadRGBAPixels = i830ReadRGBAPixels_8888;
356
357 if(imesa->hw_stencil) {
358 swdd->ReadDepthSpan = i830ReadDepthSpan_24_8;
359 swdd->WriteDepthSpan = i830WriteDepthSpan_24_8;
360 swdd->ReadDepthPixels = i830ReadDepthPixels_24_8;
361 swdd->WriteDepthPixels = i830WriteDepthPixels_24_8;
362
363 swdd->WriteStencilSpan = i830WriteStencilSpan_24_8;
364 swdd->ReadStencilSpan = i830ReadStencilSpan_24_8;
365 swdd->WriteStencilPixels = i830WriteStencilPixels_24_8;
366 swdd->ReadStencilPixels = i830ReadStencilPixels_24_8;
367 } else {
368 swdd->ReadDepthSpan = i830ReadDepthSpan_24;
369 swdd->WriteDepthSpan = i830WriteDepthSpan_24;
370 swdd->ReadDepthPixels = i830ReadDepthPixels_24;
371 swdd->WriteDepthPixels = i830WriteDepthPixels_24;
372 }
373 break;
374 }
375
376 swdd->SpanRenderStart = i830SpanRenderStart;
377 swdd->SpanRenderFinish = i830SpanRenderFinish;
378 }