1 /* $Id: s_zoom.c,v 1.4 2001/03/12 00:48:42 gareth Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 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.
30 #include "s_context.h"
32 #include "s_stencil.h"
38 * Write a span of pixels to the frame buffer while applying a pixel zoom.
39 * This is only used by glDrawPixels and glCopyPixels.
40 * Input: n - number of pixels in input row
41 * x, y - destination of the span
42 * z - depth values for the span
43 * red, green, blue, alpha - array of colors
44 * y0 - location of first row in the image we're drawing.
47 _mesa_write_zoomed_rgba_span( GLcontext
*ctx
,
48 GLuint n
, GLint x
, GLint y
, const GLdepth z
[],
50 CONST GLchan rgba
[][4], GLint y0
)
55 GLchan zrgba
[MAX_WIDTH
][4]; /* zoomed pixel colors */
56 GLdepth zdepth
[MAX_WIDTH
]; /* zoomed depth values */
57 GLfixed zfog
[MAX_WIDTH
]; /* zoomed fog values */
58 GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
59 const GLuint
*srcRGBA32
= (const GLuint
*) rgba
;
60 GLuint
*dstRGBA32
= (GLuint
*) zrgba
;
62 /* compute width of output row */
63 m
= (GLint
) ABSF( n
* ctx
->Pixel
.ZoomX
);
67 if (ctx
->Pixel
.ZoomX
<0.0) {
68 /* adjust x coordinate for left/right mirroring */
72 /* compute which rows to draw */
74 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
75 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
85 /* return early if r0...r1 is above or below window */
90 if (r0
>=ctx
->DrawBuffer
->Height
&& r1
>=ctx
->DrawBuffer
->Height
) {
95 /* check if left edge is outside window */
101 /* make sure span isn't too long or short */
109 assert( m
<= MAX_WIDTH
);
111 /* zoom the span horizontally */
112 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
115 i
= n
- (j
+skipcol
) - 1;
116 dstRGBA32
[j
] = srcRGBA32
[i
];
119 if (fog
&& ctx
->Fog
.Enabled
) {
121 i
= n
- (j
+skipcol
) - 1;
127 GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
129 i
= (GLint
) ((j
+skipcol
) * xscale
);
130 if (i
<0) i
= n
+ i
- 1;
131 dstRGBA32
[j
] = srcRGBA32
[i
];
134 if (fog
&& ctx
->Fog
.Enabled
) {
136 i
= (GLint
) ((j
+skipcol
) * xscale
);
137 if (i
<0) i
= n
+ i
- 1;
144 for (r
=r0
; r
<r1
; r
++) {
145 _mesa_write_rgba_span( ctx
, m
, x
+skipcol
, r
, zdepth
,
154 _mesa_write_zoomed_rgb_span( GLcontext
*ctx
,
155 GLuint n
, GLint x
, GLint y
, const GLdepth z
[],
157 CONST GLchan rgb
[][3], GLint y0
)
160 GLint r0
, r1
, row
, r
;
162 GLchan zrgba
[MAX_WIDTH
][4]; /* zoomed pixel colors */
163 GLdepth zdepth
[MAX_WIDTH
]; /* zoomed depth values */
164 GLfixed zfog
[MAX_WIDTH
]; /* zoomed fog values */
165 GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
167 /* compute width of output row */
168 m
= (GLint
) ABSF( n
* ctx
->Pixel
.ZoomX
);
172 if (ctx
->Pixel
.ZoomX
<0.0) {
173 /* adjust x coordinate for left/right mirroring */
177 /* compute which rows to draw */
179 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
180 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
190 /* return early if r0...r1 is above or below window */
195 if (r0
>=ctx
->DrawBuffer
->Height
&& r1
>=ctx
->DrawBuffer
->Height
) {
200 /* check if left edge is outside window */
206 /* make sure span isn't too long or short */
214 assert( m
<= MAX_WIDTH
);
216 /* zoom the span horizontally */
217 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
220 i
= n
- (j
+skipcol
) - 1;
221 zrgba
[j
][0] = rgb
[i
][0];
222 zrgba
[j
][1] = rgb
[i
][1];
223 zrgba
[j
][2] = rgb
[i
][2];
224 zrgba
[j
][3] = CHAN_MAX
;
227 if (fog
&& ctx
->Fog
.Enabled
) {
229 i
= n
- (j
+skipcol
) - 1;
235 GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
237 i
= (GLint
) ((j
+skipcol
) * xscale
);
238 if (i
<0) i
= n
+ i
- 1;
239 zrgba
[j
][0] = rgb
[i
][0];
240 zrgba
[j
][1] = rgb
[i
][1];
241 zrgba
[j
][2] = rgb
[i
][2];
242 zrgba
[j
][3] = CHAN_MAX
;
245 if (fog
&& ctx
->Fog
.Enabled
) {
247 i
= (GLint
) ((j
+skipcol
) * xscale
);
248 if (i
<0) i
= n
+ i
- 1;
255 for (r
=r0
; r
<r1
; r
++) {
256 _mesa_write_rgba_span( ctx
, m
, x
+skipcol
, r
, zdepth
,
257 (fog
? zfog
: 0), zrgba
, GL_BITMAP
);
264 * As above, but write CI pixels.
267 _mesa_write_zoomed_index_span( GLcontext
*ctx
,
268 GLuint n
, GLint x
, GLint y
, const GLdepth z
[],
270 const GLuint indexes
[], GLint y0
)
273 GLint r0
, r1
, row
, r
;
275 GLuint zindexes
[MAX_WIDTH
]; /* zoomed color indexes */
276 GLdepth zdepth
[MAX_WIDTH
]; /* zoomed depth values */
277 GLfixed zfog
[MAX_WIDTH
]; /* zoomed fog values */
278 GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
280 /* compute width of output row */
281 m
= (GLint
) ABSF( n
* ctx
->Pixel
.ZoomX
);
285 if (ctx
->Pixel
.ZoomX
<0.0) {
286 /* adjust x coordinate for left/right mirroring */
290 /* compute which rows to draw */
292 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
293 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
303 /* return early if r0...r1 is above or below window */
308 if (r0
>=ctx
->DrawBuffer
->Height
&& r1
>=ctx
->DrawBuffer
->Height
) {
313 /* check if left edge is outside window */
319 /* make sure span isn't too long or short */
327 assert( m
<= MAX_WIDTH
);
329 /* zoom the span horizontally */
330 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
333 i
= n
- (j
+skipcol
) - 1;
334 zindexes
[j
] = indexes
[i
];
337 if (fog
&& ctx
->Fog
.Enabled
) {
339 i
= n
- (j
+skipcol
) - 1;
345 GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
347 i
= (GLint
) ((j
+skipcol
) * xscale
);
348 if (i
<0) i
= n
+ i
- 1;
349 zindexes
[j
] = indexes
[i
];
352 if (fog
&& ctx
->Fog
.Enabled
) {
354 i
= (GLint
) ((j
+skipcol
) * xscale
);
355 if (i
<0) i
= n
+ i
- 1;
362 for (r
=r0
; r
<r1
; r
++) {
363 _mesa_write_index_span( ctx
, m
, x
+skipcol
, r
, zdepth
,
364 (fog
? zfog
: 0), zindexes
, GL_BITMAP
);
371 * As above, but write stencil values.
374 _mesa_write_zoomed_stencil_span( GLcontext
*ctx
,
375 GLuint n
, GLint x
, GLint y
,
376 const GLstencil stencil
[], GLint y0
)
379 GLint r0
, r1
, row
, r
;
381 GLstencil zstencil
[MAX_WIDTH
]; /* zoomed stencil values */
382 GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
384 /* compute width of output row */
385 m
= (GLint
) ABSF( n
* ctx
->Pixel
.ZoomX
);
389 if (ctx
->Pixel
.ZoomX
<0.0) {
390 /* adjust x coordinate for left/right mirroring */
394 /* compute which rows to draw */
396 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
397 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
407 /* return early if r0...r1 is above or below window */
412 if (r0
>=ctx
->DrawBuffer
->Height
&& r1
>=ctx
->DrawBuffer
->Height
) {
417 /* check if left edge is outside window */
423 /* make sure span isn't too long or short */
431 assert( m
<= MAX_WIDTH
);
433 /* zoom the span horizontally */
434 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
437 i
= n
- (j
+skipcol
) - 1;
438 zstencil
[j
] = stencil
[i
];
442 GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
444 i
= (GLint
) ((j
+skipcol
) * xscale
);
445 if (i
<0) i
= n
+ i
- 1;
446 zstencil
[j
] = stencil
[i
];
451 for (r
=r0
; r
<r1
; r
++) {
452 _mesa_write_stencil_span( ctx
, m
, x
+skipcol
, r
, zstencil
);