1 /* $Id: s_zoom.c,v 1.13 2002/02/02 17:24:11 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #include "s_context.h"
34 #include "s_stencil.h"
39 * Helper function called from _mesa_write_zoomed_rgba/rgb/index_span().
42 zoom_span( GLcontext
*ctx
, const struct sw_span
*span
,
43 const GLvoid
*src
, GLint y0
, GLenum format
)
46 GLint c0
, c1
, skipCol
;
48 const GLint maxWidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
49 GLchan rgbaSave
[MAX_WIDTH
][4];
50 GLuint indexSave
[MAX_WIDTH
];
51 struct sw_span zoomed
;
52 const GLchan (*rgba
)[4] = (const GLchan (*)[4]) src
;
53 const GLchan (*rgb
)[3] = (const GLchan (*)[3]) src
;
54 const GLuint
*indexes
= (const GLuint
*) src
;
56 /* no pixel arrays! */
57 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
60 if (format
== GL_RGBA
|| format
== GL_RGB
) {
62 zoomed
.zStep
= span
->z
;
63 zoomed
.fog
= span
->fog
;
64 zoomed
.fogStep
= span
->fogStep
;
65 zoomed
.interpMask
= span
->interpMask
& ~SPAN_RGBA
;
66 zoomed
.arrayMask
|= SPAN_RGBA
;
68 else if (format
== GL_COLOR_INDEX
) {
70 zoomed
.zStep
= span
->z
;
71 zoomed
.fog
= span
->fog
;
72 zoomed
.fogStep
= span
->fogStep
;
73 zoomed
.interpMask
= span
->interpMask
& ~SPAN_INDEX
;
74 zoomed
.arrayMask
|= SPAN_INDEX
;
78 * Compute which columns to draw: [c0, c1)
81 c1
= (GLint
) (span
->x
+ span
->end
* ctx
->Pixel
.ZoomX
);
100 zoomed
.end
= c1
- c0
;
103 if (zoomed
.end
> maxWidth
)
104 zoomed
.end
= maxWidth
;
107 * Compute which rows to draw: [r0, r1)
110 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
111 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
126 * Trivial clip rejection testing.
128 if (r1
< 0) /* below window */
130 if (r0
>= ctx
->DrawBuffer
->Height
) /* above window */
132 if (c1
< 0) /* left of window */
134 if (c0
>= ctx
->DrawBuffer
->Width
) /* right of window */
137 /* zoom the span horizontally */
138 if (format
== GL_RGBA
) {
139 if (ctx
->Pixel
.ZoomX
== -1.0F
) {
141 for (j
= zoomed
.start
; j
< zoomed
.end
; j
++) {
142 i
= span
->end
- (j
+ skipCol
) - 1;
143 COPY_CHAN4(zoomed
.color
.rgba
[j
], rgba
[i
]);
147 /* general solution */
148 const GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
149 for (j
= zoomed
.start
; j
< zoomed
.end
; j
++) {
150 i
= (GLint
) ((j
+ skipCol
) * xscale
);
152 i
= span
->end
+ i
- 1;
153 COPY_CHAN4(zoomed
.color
.rgba
[j
], rgba
[i
]);
157 else if (format
== GL_RGB
) {
158 if (ctx
->Pixel
.ZoomX
== -1.0F
) {
160 for (j
= zoomed
.start
; j
< zoomed
.end
; j
++) {
161 i
= span
->end
- (j
+ skipCol
) - 1;
162 zoomed
.color
.rgba
[j
][0] = rgb
[i
][0];
163 zoomed
.color
.rgba
[j
][1] = rgb
[i
][1];
164 zoomed
.color
.rgba
[j
][2] = rgb
[i
][2];
165 zoomed
.color
.rgba
[j
][3] = CHAN_MAX
;
169 /* general solution */
170 const GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
171 for (j
= zoomed
.start
; j
< zoomed
.end
; j
++) {
172 i
= (GLint
) ((j
+ skipCol
) * xscale
);
174 i
= span
->end
+ i
- 1;
175 zoomed
.color
.rgba
[j
][0] = rgb
[i
][0];
176 zoomed
.color
.rgba
[j
][1] = rgb
[i
][1];
177 zoomed
.color
.rgba
[j
][2] = rgb
[i
][2];
178 zoomed
.color
.rgba
[j
][3] = CHAN_MAX
;
182 else if (format
== GL_COLOR_INDEX
) {
183 if (ctx
->Pixel
.ZoomX
== -1.0F
) {
185 for (j
= zoomed
.start
; j
< zoomed
.end
; j
++) {
186 i
= span
->end
- (j
+ skipCol
) - 1;
187 zoomed
.color
.index
[j
] = indexes
[i
];
191 /* general solution */
192 const GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
193 for (j
= zoomed
.start
; j
< zoomed
.end
; j
++) {
194 i
= (GLint
) ((j
+ skipCol
) * xscale
);
196 i
= span
->end
+ i
- 1;
197 zoomed
.color
.index
[j
] = indexes
[i
];
202 /* write the span in rows [r0, r1) */
203 if (format
== GL_RGBA
|| format
== GL_RGB
) {
204 /* Writing the span may modify the colors, so make a backup now if we're
205 * going to call _mesa_write_zoomed_span() more than once.
208 MEMCPY(rgbaSave
, zoomed
.color
.rgba
, zoomed
.end
* 4 * sizeof(GLchan
));
210 for (zoomed
.y
= r0
; zoomed
.y
< r1
; zoomed
.y
++) {
211 _mesa_write_rgba_span(ctx
, &zoomed
, GL_BITMAP
);
213 /* restore the colors */
214 MEMCPY(zoomed
.color
.rgba
, rgbaSave
, zoomed
.end
*4 * sizeof(GLchan
));
218 else if (format
== GL_COLOR_INDEX
) {
220 MEMCPY(indexSave
, zoomed
.color
.index
, zoomed
.end
* sizeof(GLuint
));
222 for (zoomed
.y
= r0
; zoomed
.y
< r1
; zoomed
.y
++) {
223 _mesa_write_index_span(ctx
, &zoomed
, GL_BITMAP
);
225 /* restore the colors */
226 MEMCPY(zoomed
.color
.index
, indexSave
, zoomed
.end
* sizeof(GLuint
));
234 _mesa_write_zoomed_rgba_span( GLcontext
*ctx
, const struct sw_span
*span
,
235 CONST GLchan rgba
[][4], GLint y0
)
237 zoom_span(ctx
, span
, (const GLvoid
*) rgba
, y0
, GL_RGBA
);
242 _mesa_write_zoomed_rgb_span( GLcontext
*ctx
, const struct sw_span
*span
,
243 CONST GLchan rgb
[][3], GLint y0
)
245 zoom_span(ctx
, span
, (const GLvoid
*) rgb
, y0
, GL_RGB
);
250 _mesa_write_zoomed_index_span( GLcontext
*ctx
, const struct sw_span
*span
,
253 zoom_span(ctx
, span
, (const GLvoid
*) span
->color
.index
, y0
, GL_COLOR_INDEX
);
258 * As above, but write stencil values.
261 _mesa_write_zoomed_stencil_span( GLcontext
*ctx
,
262 GLuint n
, GLint x
, GLint y
,
263 const GLstencil stencil
[], GLint y0
)
266 GLint r0
, r1
, row
, r
;
268 GLstencil zstencil
[MAX_WIDTH
]; /* zoomed stencil values */
269 GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
271 /* compute width of output row */
272 m
= (GLint
) ABSF( n
* ctx
->Pixel
.ZoomX
);
276 if (ctx
->Pixel
.ZoomX
<0.0) {
277 /* adjust x coordinate for left/right mirroring */
281 /* compute which rows to draw */
283 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
284 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
294 /* return early if r0...r1 is above or below window */
299 if (r0
>=ctx
->DrawBuffer
->Height
&& r1
>=ctx
->DrawBuffer
->Height
) {
304 /* check if left edge is outside window */
310 /* make sure span isn't too long or short */
318 ASSERT( m
<= MAX_WIDTH
);
320 /* zoom the span horizontally */
321 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
324 i
= n
- (j
+skipcol
) - 1;
325 zstencil
[j
] = stencil
[i
];
329 GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
331 i
= (GLint
) ((j
+skipcol
) * xscale
);
332 if (i
<0) i
= n
+ i
- 1;
333 zstencil
[j
] = stencil
[i
];
338 for (r
=r0
; r
<r1
; r
++) {
339 _mesa_write_stencil_span( ctx
, m
, x
+skipcol
, r
, zstencil
);