3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include "s_context.h"
33 #include "s_stencil.h"
38 * Helper function called from _swrast_write_zoomed_rgba/rgb/index_span().
41 zoom_span( GLcontext
*ctx
, const struct sw_span
*span
,
42 const GLvoid
*src
, GLint y0
, GLenum format
, GLint skipPixels
)
45 GLint c0
, c1
, skipCol
;
47 const GLuint maxWidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
48 GLchan rgbaSave
[MAX_WIDTH
][4];
49 GLuint indexSave
[MAX_WIDTH
];
50 const GLchan (*rgba
)[4] = (const GLchan (*)[4]) src
;
51 const GLchan (*rgb
)[3] = (const GLchan (*)[3]) src
;
52 const GLuint
*indexes
= (const GLuint
*) src
;
53 struct sw_span zoomed
;
54 struct span_arrays zoomed_arrays
; /* this is big! */
56 /* no pixel arrays! */
57 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
58 ASSERT(span
->primitive
== GL_BITMAP
);
60 INIT_SPAN(zoomed
, GL_BITMAP
, 0, 0, 0);
61 zoomed
.array
= &zoomed_arrays
;
64 zoomed
.zStep
= span
->zStep
; /* span->zStep == 0 */
65 zoomed
.fog
= span
->fog
;
66 zoomed
.fogStep
= span
->fogStep
;
67 if (format
== GL_RGBA
|| format
== GL_RGB
) {
68 zoomed
.interpMask
= span
->interpMask
& ~SPAN_RGBA
;
69 zoomed
.arrayMask
|= SPAN_RGBA
;
71 else if (format
== GL_COLOR_INDEX
) {
72 zoomed
.interpMask
= span
->interpMask
& ~SPAN_INDEX
;
73 zoomed
.arrayMask
|= SPAN_INDEX
;
77 * Compute which columns to draw: [c0, c1)
81 c1
= (GLint
) (span
->x
+ span
->end
* ctx
->Pixel
.ZoomX
);
83 c0
= (GLint
) (span
->x
+ skipPixels
* ctx
->Pixel
.ZoomX
);
84 c1
= (GLint
) (span
->x
+ (skipPixels
+ span
->end
) * ctx
->Pixel
.ZoomX
);
104 zoomed
.end
= c1
- c0
;
107 if (zoomed
.end
> maxWidth
)
108 zoomed
.end
= maxWidth
;
111 * Compute which rows to draw: [r0, r1)
114 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
115 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
130 * Trivial clip rejection testing.
132 if (r1
< 0) /* below window */
134 if (r0
>= (GLint
) ctx
->DrawBuffer
->Height
) /* above window */
136 if (c1
< 0) /* left of window */
138 if (c0
>= (GLint
) ctx
->DrawBuffer
->Width
) /* right of window */
141 /* zoom the span horizontally */
142 if (format
== GL_RGBA
) {
143 if (ctx
->Pixel
.ZoomX
== -1.0F
) {
145 for (j
= (GLint
) zoomed
.start
; j
< (GLint
) zoomed
.end
; j
++) {
146 i
= span
->end
- (j
+ skipCol
) - 1;
147 COPY_CHAN4(zoomed
.array
->rgba
[j
], rgba
[i
]);
151 /* general solution */
152 const GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
153 for (j
= (GLint
) zoomed
.start
; j
< (GLint
) zoomed
.end
; j
++) {
154 i
= (GLint
) ((j
+ skipCol
) * xscale
);
155 if (ctx
->Pixel
.ZoomX
< 0.0) {
157 i
= span
->end
+ i
- 1;
160 ASSERT(i
< (GLint
) span
->end
);
161 COPY_CHAN4(zoomed
.array
->rgba
[j
], rgba
[i
]);
165 else if (format
== GL_RGB
) {
166 if (ctx
->Pixel
.ZoomX
== -1.0F
) {
168 for (j
= (GLint
) zoomed
.start
; j
< (GLint
) zoomed
.end
; j
++) {
169 i
= span
->end
- (j
+ skipCol
) - 1;
170 zoomed
.array
->rgba
[j
][0] = rgb
[i
][0];
171 zoomed
.array
->rgba
[j
][1] = rgb
[i
][1];
172 zoomed
.array
->rgba
[j
][2] = rgb
[i
][2];
173 zoomed
.array
->rgba
[j
][3] = CHAN_MAX
;
177 /* general solution */
178 const GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
179 for (j
= (GLint
) zoomed
.start
; j
< (GLint
) zoomed
.end
; j
++) {
180 i
= (GLint
) ((j
+ skipCol
) * xscale
);
181 if (ctx
->Pixel
.ZoomX
< 0.0) {
183 i
= span
->end
+ i
- 1;
186 ASSERT(i
< (GLint
) span
->end
);
187 zoomed
.array
->rgba
[j
][0] = rgb
[i
][0];
188 zoomed
.array
->rgba
[j
][1] = rgb
[i
][1];
189 zoomed
.array
->rgba
[j
][2] = rgb
[i
][2];
190 zoomed
.array
->rgba
[j
][3] = CHAN_MAX
;
194 else if (format
== GL_COLOR_INDEX
) {
195 if (ctx
->Pixel
.ZoomX
== -1.0F
) {
197 for (j
= (GLint
) zoomed
.start
; j
< (GLint
) zoomed
.end
; j
++) {
198 i
= span
->end
- (j
+ skipCol
) - 1;
199 zoomed
.array
->index
[j
] = indexes
[i
];
203 /* general solution */
204 const GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
205 for (j
= (GLint
) zoomed
.start
; j
< (GLint
) zoomed
.end
; j
++) {
206 i
= (GLint
) ((j
+ skipCol
) * xscale
);
207 if (ctx
->Pixel
.ZoomX
< 0.0) {
209 i
= span
->end
+ i
- 1;
212 ASSERT(i
< (GLint
) span
->end
);
213 zoomed
.array
->index
[j
] = indexes
[i
];
218 /* write the span in rows [r0, r1) */
219 if (format
== GL_RGBA
|| format
== GL_RGB
) {
220 /* Writing the span may modify the colors, so make a backup now if we're
221 * going to call _swrast_write_zoomed_span() more than once.
222 * Also, clipping may change the span end value, so store it as well.
224 const GLint end
= zoomed
.end
; /* save */
226 MEMCPY(rgbaSave
, zoomed
.array
->rgba
, zoomed
.end
* 4 * sizeof(GLchan
));
228 for (zoomed
.y
= r0
; zoomed
.y
< r1
; zoomed
.y
++) {
229 _swrast_write_rgba_span(ctx
, &zoomed
);
230 zoomed
.end
= end
; /* restore */
232 /* restore the colors */
233 MEMCPY(zoomed
.array
->rgba
, rgbaSave
, zoomed
.end
*4 * sizeof(GLchan
));
237 else if (format
== GL_COLOR_INDEX
) {
238 const GLint end
= zoomed
.end
; /* save */
240 MEMCPY(indexSave
, zoomed
.array
->index
, zoomed
.end
* sizeof(GLuint
));
242 for (zoomed
.y
= r0
; zoomed
.y
< r1
; zoomed
.y
++) {
243 _swrast_write_index_span(ctx
, &zoomed
);
244 zoomed
.end
= end
; /* restore */
246 /* restore the colors */
247 MEMCPY(zoomed
.array
->index
, indexSave
, zoomed
.end
* sizeof(GLuint
));
255 _swrast_write_zoomed_rgba_span( GLcontext
*ctx
, const struct sw_span
*span
,
256 CONST GLchan rgba
[][4], GLint y0
,
259 zoom_span(ctx
, span
, (const GLvoid
*) rgba
, y0
, GL_RGBA
, skipPixels
);
264 _swrast_write_zoomed_rgb_span( GLcontext
*ctx
, const struct sw_span
*span
,
265 CONST GLchan rgb
[][3], GLint y0
,
268 zoom_span(ctx
, span
, (const GLvoid
*) rgb
, y0
, GL_RGB
, skipPixels
);
273 _swrast_write_zoomed_index_span( GLcontext
*ctx
, const struct sw_span
*span
,
274 GLint y0
, GLint skipPixels
)
276 zoom_span(ctx
, span
, (const GLvoid
*) span
->array
->index
, y0
,
277 GL_COLOR_INDEX
, skipPixels
);
282 * As above, but write stencil values.
285 _swrast_write_zoomed_stencil_span( GLcontext
*ctx
,
286 GLuint n
, GLint x
, GLint y
,
287 const GLstencil stencil
[], GLint y0
,
291 GLint r0
, r1
, row
, r
;
293 GLstencil zstencil
[MAX_WIDTH
]; /* zoomed stencil values */
294 GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
296 (void) skipPixels
; /* XXX this shouldn't be ignored */
298 /* compute width of output row */
299 m
= (GLint
) FABSF( n
* ctx
->Pixel
.ZoomX
);
303 if (ctx
->Pixel
.ZoomX
<0.0) {
304 /* adjust x coordinate for left/right mirroring */
308 /* compute which rows to draw */
310 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
311 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
321 /* return early if r0...r1 is above or below window */
326 if (r0
>= (GLint
) ctx
->DrawBuffer
->Height
&&
327 r1
>= (GLint
) ctx
->DrawBuffer
->Height
) {
332 /* check if left edge is outside window */
338 /* make sure span isn't too long or short */
346 ASSERT( m
<= MAX_WIDTH
);
348 /* zoom the span horizontally */
349 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
352 i
= n
- (j
+skipcol
) - 1;
353 zstencil
[j
] = stencil
[i
];
357 GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
359 i
= (GLint
) ((j
+skipcol
) * xscale
);
360 if (i
<0) i
= n
+ i
- 1;
361 zstencil
[j
] = stencil
[i
];
366 for (r
=r0
; r
<r1
; r
++) {
367 _swrast_write_stencil_span( ctx
, m
, x
+skipcol
, r
, zstencil
);