Add support for optimized versions of the code underlying ReadPixels
[mesa.git] / src / mesa / drivers / dri / unichrome / via_span.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "glheader.h"
26 #include "macros.h"
27 #include "mtypes.h"
28 #include "colormac.h"
29 #include "via_context.h"
30 #include "via_span.h"
31 #include "via_ioctl.h"
32 #include "swrast/swrast.h"
33
34 #define DBG 0
35 #define LOCAL_VARS \
36 __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
37 viaScreenPrivate *viaScreen = vmesa->viaScreen; \
38 GLuint pitch = vmesa->drawPitch; \
39 GLuint height = dPriv->h; \
40 GLushort p; \
41 char *buf = (char *)(vmesa->drawMap + \
42 dPriv->x * viaScreen->bytesPerPixel + \
43 dPriv->y * pitch); \
44 char *read_buf = (char *)(vmesa->readMap + \
45 dPriv->x * viaScreen->bytesPerPixel + \
46 dPriv->y * pitch); \
47 (void)read_buf; (void)buf; (void)p
48
49 #define LOCAL_DEPTH_VARS \
50 __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
51 viaScreenPrivate *viaScreen = vmesa->viaScreen; \
52 GLuint pitch = viaScreen->backPitch; \
53 GLuint height = dPriv->h; \
54 char *buf = (char *)(vmesa->depth.map + \
55 dPriv->x * 2 + \
56 dPriv->y * pitch)
57
58 #define CLIPPIXEL(_x,_y) (_x >= minx && _x < maxx && \
59 _y >= miny && _y < maxy)
60
61
62 #define CLIPSPAN(_x, _y, _n, _x1, _n1, _i) \
63 if (_y < miny || _y >= maxy) { \
64 _n1 = 0, _x1 = x; \
65 } \
66 else { \
67 _n1 = _n; \
68 _x1 = _x; \
69 if (_x1 < minx) _i += (minx -_x1), n1 -= (minx -_x1), _x1 = minx; \
70 if (_x1 + _n1 >= maxx) n1 -= (_x1 + n1 - maxx); \
71 }
72
73 #define Y_FLIP(_y) (height - _y - 1)
74
75 #define HW_LOCK() \
76 viaContextPtr vmesa = VIA_CONTEXT(ctx); \
77 LOCK_HARDWARE_QUIESCENT(vmesa);
78
79 /*=* [DBG] csmash saam : bitmap option menu can't be drawn in saam *=*/
80 /*#define HW_CLIPLOOP() \
81 do { \
82 __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
83 int _nc = dPriv->numClipRects; \
84 while (_nc--) { \
85 int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
86 int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
87 int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
88 int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;*/
89 #define HW_CLIPLOOP() \
90 do { \
91 __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
92 int _nc = dPriv->numClipRects; \
93 GLuint scrn = vmesa->saam & S_MASK; \
94 if(scrn == S1) _nc = 1; \
95 while (_nc--) { \
96 int minx; \
97 int miny; \
98 int maxx; \
99 int maxy; \
100 if (!vmesa->saam) { \
101 minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
102 miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
103 maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
104 maxy = dPriv->pClipRects[_nc].y2 - dPriv->y; \
105 } \
106 else { \
107 minx = -10000; \
108 miny = -10000; \
109 maxx = 10000; \
110 maxy = 10000; \
111 }
112
113 /*else if (scrn == S0) { \
114 minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
115 miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
116 maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
117 maxy = dPriv->pClipRects[_nc].y2 - dPriv->y; \
118 } \
119 else if (scrn == S1) { \
120 drm_clip_rect_t *b = vmesa->sarea->boxes; \
121 minx = b->x1; \
122 miny = b->y1; \
123 maxx = b->x2; \
124 maxy = b->y2; \
125 } \
126 else { \
127 drm_clip_rect_t *b = vmesa->sarea->boxes + vmesa->numClipRects;\
128 minx = b->x1; \
129 miny = b->y1; \
130 maxx = b->x2; \
131 maxy = b->y2; \
132 }*/
133
134 #define HW_ENDCLIPLOOP() \
135 } \
136 } while (0)
137
138 #define HW_UNLOCK() \
139 UNLOCK_HARDWARE(vmesa);
140
141
142 /* 16 bit, 565 rgb color spanline and pixel functions
143 */
144 /*=* [DBG] csmash : fix options worng position *=*/
145 /*#define LOCAL_VARS \
146 __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
147 GLuint pitch = vmesa->drawPitch; \
148 GLuint height = dPriv->h; \
149 GLushort p; \
150 char *buf = (char *)(vmesa->drawMap + \
151 dPriv->x * 2 + \
152 dPriv->y * pitch); \
153 char *read_buf = (char *)(vmesa->readMap + \
154 dPriv->x * 2 + \
155 dPriv->y * pitch); \
156 (void)read_buf; (void)buf; (void)p*/
157
158 #undef LOCAL_VARS
159 #define LOCAL_VARS \
160 __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
161 GLuint pitch = vmesa->drawPitch; \
162 GLuint height = dPriv->h; \
163 GLushort p; \
164 char *buf, *read_buf; \
165 p = 0; \
166 if (vmesa->glCtx->Color._DrawDestMask[0] == __GL_BACK_BUFFER_MASK) { \
167 buf = (char *)(vmesa->drawMap); \
168 read_buf = (char *)(vmesa->readMap); \
169 } \
170 else { \
171 buf = (char *)(vmesa->drawMap + \
172 dPriv->x * 2 + \
173 dPriv->y * pitch); \
174 read_buf = (char *)(vmesa->readMap + \
175 dPriv->x * 2 + \
176 dPriv->y * pitch); \
177 }
178
179 #define INIT_MONO_PIXEL(p, color) \
180 p = PACK_COLOR_565(color[0], color[1], color[2])
181
182 #define WRITE_RGBA(_x, _y, r, g, b, a) \
183 *(GLushort *)(buf + _x * 2 + _y * pitch) = ((((int)r & 0xf8) << 8) | \
184 (((int)g & 0xfc) << 3) | \
185 (((int)b & 0xf8) >> 3))
186
187 #define WRITE_PIXEL(_x, _y, p) \
188 *(GLushort *)(buf + _x * 2 + _y * pitch) = p
189
190 #define READ_RGBA(rgba, _x, _y) \
191 do { \
192 GLushort p = *(GLushort *)(read_buf + _x * 2 + _y * pitch); \
193 rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
194 rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
195 rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
196 rgba[3] = 255; \
197 } while (0)
198
199 #define TAG(x) via##x##_565
200 #include "spantmp.h"
201
202 /* 32 bit, 8888 argb color spanline and pixel functions
203 */
204 #undef LOCAL_VARS
205 #undef LOCAL_DEPTH_VARS
206
207 #define LOCAL_VARS \
208 __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
209 GLuint pitch = vmesa->drawPitch; \
210 GLuint height = dPriv->h; \
211 GLuint p; \
212 char *buf, *read_buf; \
213 p = 0; \
214 if (vmesa->glCtx->Color._DrawDestMask[0] == __GL_BACK_BUFFER_MASK) { \
215 buf = (char *)(vmesa->drawMap); \
216 read_buf = (char *)(vmesa->readMap); \
217 } \
218 else { \
219 buf = (char *)(vmesa->drawMap + \
220 dPriv->x * 4 + \
221 dPriv->y * pitch); \
222 read_buf = (char *)(vmesa->readMap + \
223 dPriv->x * 4 + \
224 dPriv->y * pitch); \
225 }
226
227 #define GET_SRC_PTR(_x, _y) (read_buf + _x * 4 + _y * pitch)
228 #define GET_DST_PTR(_x, _y) ( buf + _x * 4 + _y * pitch)
229 #define SPANTMP_PIXEL_FMT GL_BGRA
230 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
231
232 #define TAG(x) via##x##_8888
233 #define TAG2(x,y) via##x##_8888##y
234 #include "spantmp2.h"
235
236
237 /* 16 bit depthbuffer functions.
238 */
239 /*=* John Sheng [2003.6.16] fix exy press 'i' dirty screen *=*/
240 /*#define LOCAL_DEPTH_VARS \
241 __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
242 GLuint pitch = vmesa->depth.pitch; \
243 GLuint height = dPriv->h; \
244 char *buf = (char *)(vmesa->depth.map + \
245 dPriv->x * 2 + \
246 dPriv->y * pitch) */
247 #define LOCAL_DEPTH_VARS \
248 __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
249 /*viaScreenPrivate *viaScreen = vmesa->viaScreen;*/ \
250 GLuint pitch = vmesa->depth.pitch; \
251 GLuint height = dPriv->h; \
252 char *buf = (char *)(vmesa->depth.map)
253
254
255 #define WRITE_DEPTH(_x, _y, d) \
256 *(GLushort *)(buf + _x * 2 + _y * pitch) = d;
257
258 #define READ_DEPTH(d, _x, _y) \
259 d = *(GLushort *)(buf + _x * 2 + _y * pitch);
260
261 #define TAG(x) via##x##_16
262 #include "depthtmp.h"
263
264 /* 32 bit depthbuffer functions.
265 */
266 #define WRITE_DEPTH(_x, _y, d) \
267 *(GLuint *)(buf + _x * 4 + _y * pitch) = d;
268
269 #define READ_DEPTH(d, _x, _y) \
270 d = *(GLuint *)(buf + _x * 4 + _y * pitch);
271
272 #define TAG(x) via##x##_32
273 #include "depthtmp.h"
274
275 /* 24/8 bit depthbuffer functions.
276 */
277 /*
278 #define WRITE_DEPTH(_x, _y, d) { \
279 GLuint tmp = *(GLuint *)(buf + _x * 4 + y * pitch); \
280 tmp &= 0xff; \
281 tmp |= (d) & 0xffffff00; \
282 *(GLuint *)(buf + _x * 4 + _y * pitch) = tmp; \
283
284 #define READ_DEPTH(d, _x, _y) \
285 d = (*(GLuint *)(buf + _x * 4 + _y * pitch) & ~0xff) >> 8;
286
287 #define TAG(x) via##x##_24_8
288 #include "depthtmp.h"
289 */
290
291
292 static void viaSetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer,
293 GLuint bufferBit)
294 {
295 viaContextPtr vmesa = VIA_CONTEXT(ctx);
296 #ifdef DEBUG
297 if (VIA_DEBUG) fprintf(stderr, "%s in\n", __FUNCTION__);
298 #endif
299 if (bufferBit == DD_FRONT_LEFT_BIT) {
300 vmesa->drawMap = (char *)vmesa->driScreen->pFB;
301 vmesa->readMap = (char *)vmesa->driScreen->pFB;
302 vmesa->drawPitch = vmesa->front.pitch;
303 vmesa->readPitch = vmesa->front.pitch;
304 }
305 else if (bufferBit == DD_BACK_LEFT_BIT) {
306 vmesa->drawMap = vmesa->back.map;
307 vmesa->readMap = vmesa->back.map;
308 vmesa->drawPitch = vmesa->back.pitch;
309 vmesa->readPitch = vmesa->back.pitch;
310 }
311 else {
312 ASSERT(0);
313 }
314 #ifdef DEBUG
315 if (VIA_DEBUG) fprintf(stderr, "%s out\n", __FUNCTION__);
316 #endif
317 }
318
319
320 void viaInitSpanFuncs(GLcontext *ctx)
321 {
322 viaContextPtr vmesa = VIA_CONTEXT(ctx);
323 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
324
325 swdd->SetBuffer = viaSetBuffer;
326 #ifdef DEBUG
327 if (VIA_DEBUG) fprintf(stderr, "%s in\n", __FUNCTION__);
328 #endif
329 if (vmesa->viaScreen->bitsPerPixel == 0x10) {
330 swdd->WriteRGBASpan = viaWriteRGBASpan_565;
331 swdd->WriteRGBSpan = viaWriteRGBSpan_565;
332 swdd->WriteMonoRGBASpan = viaWriteMonoRGBASpan_565;
333 swdd->WriteRGBAPixels = viaWriteRGBAPixels_565;
334 swdd->WriteMonoRGBAPixels = viaWriteMonoRGBAPixels_565;
335 swdd->ReadRGBASpan = viaReadRGBASpan_565;
336 swdd->ReadRGBAPixels = viaReadRGBAPixels_565;
337 }
338 else if (vmesa->viaScreen->bitsPerPixel == 0x20) {
339 viaInitPointers_8888( swdd );
340 }
341 else
342 ASSERT(0);
343
344 if (vmesa->glCtx->Visual.depthBits == 0x10) {
345 swdd->ReadDepthSpan = viaReadDepthSpan_16;
346 swdd->WriteDepthSpan = viaWriteDepthSpan_16;
347 swdd->ReadDepthPixels = viaReadDepthPixels_16;
348 swdd->WriteDepthPixels = viaWriteDepthPixels_16;
349 }
350 else if (vmesa->glCtx->Visual.depthBits == 0x20) {
351 swdd->ReadDepthSpan = viaReadDepthSpan_32;
352 swdd->WriteDepthSpan = viaWriteDepthSpan_32;
353 swdd->ReadDepthPixels = viaReadDepthPixels_32;
354 swdd->WriteDepthPixels = viaWriteDepthPixels_32;
355 }
356
357 swdd->WriteCI8Span = NULL;
358 swdd->WriteCI32Span = NULL;
359 swdd->WriteMonoCISpan = NULL;
360 swdd->WriteCI32Pixels = NULL;
361 swdd->WriteMonoCIPixels = NULL;
362 swdd->ReadCI32Span = NULL;
363 swdd->ReadCI32Pixels = NULL;
364 #ifdef DEBUG
365 if (VIA_DEBUG) fprintf(stderr, "%s out\n", __FUNCTION__);
366 #endif
367 }