516a5bb5826f20e7e36e78c743ca2cc5356c8bcc
1 /* $Id: s_zoom.c,v 1.11 2002/01/28 03:42:28 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"
40 #define SAVE_SPAN(span) struct sw_span tmp_span = (span);
42 #define RESTORE_SPAN(span) \
45 for (i=tmp_span.start; i<tmp_span.end; i++) { \
46 if (tmp_span.color.rgba[i][RCOMP] != \
47 (span).color.rgba[i][RCOMP] || \
48 tmp_span.color.rgba[i][GCOMP] != \
49 (span).color.rgba[i][GCOMP] || \
50 tmp_span.color.rgba[i][BCOMP] != \
51 (span).color.rgba[i][BCOMP]) { \
52 fprintf(stderr, "glZoom: Color-span changed in subfunction."); \
54 if (tmp_span.zArray[i] != (span).zArray[i]) { \
55 fprintf(stderr, "glZoom: Depth-span changed in subfunction."); \
61 #else /* DEBUG not defined */
63 #define SAVE_SPAN(span) GLint start = (span).start, end = (span).end;
64 #define RESTORE_SPAN(span) (span).start = start, (span).end = end; \
65 (span).writeAll = GL_TRUE;
70 * Write a span of pixels to the frame buffer while applying a pixel zoom.
71 * This is only used by glDrawPixels and glCopyPixels.
72 * Input: n - number of pixels in input row
73 * x, y - destination of the span
74 * z - depth values for the span
75 * red, green, blue, alpha - array of colors
76 * y0 - location of first row in the image we're drawing.
79 _mesa_write_zoomed_rgba_span( GLcontext
*ctx
,
80 GLuint n
, GLint x
, GLint y
, const GLdepth z
[],
82 CONST GLchan rgba
[][4], GLint y0
)
86 const GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
87 struct sw_span zoomed
;
90 zoomed
.arrayMask
|= SPAN_RGBA
;
92 /* compute width of output row */
93 zoomed
.end
= (GLint
) ABSF( n
* ctx
->Pixel
.ZoomX
);
94 if (zoomed
.end
== 0) {
97 /*here ok or better latter? like it was before */
98 else if (zoomed
.end
> maxwidth
) {
99 zoomed
.end
= maxwidth
;
102 if (ctx
->Pixel
.ZoomX
<0.0) {
103 /* adjust x coordinate for left/right mirroring */
104 zoomed
.x
= x
- zoomed
.end
;
110 /* compute which rows to draw */
112 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
113 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
123 /* return early if r0...r1 is above or below window */
128 if (r0
>=ctx
->DrawBuffer
->Height
&& r1
>=ctx
->DrawBuffer
->Height
) {
133 /* check if left edge is outside window */
138 /* make sure span isn't too long or short */
143 if (zoomed
.end
<= zoomed
.start
) {
147 ASSERT( zoomed
.end
<= MAX_WIDTH
);
149 /* zoom the span horizontally */
150 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
152 for (j
=zoomed
.start
; j
<zoomed
.end
; j
++) {
154 COPY_CHAN4(zoomed
.color
.rgba
[j
], rgba
[i
]);
155 zoomed
.zArray
[j
] = z
[i
];
157 if (fog
&& ctx
->Fog
.Enabled
) {
158 for (j
=zoomed
.start
; j
<zoomed
.end
; j
++) {
160 zoomed
.fogArray
[j
] = fog
[i
];
165 const GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
166 for (j
=zoomed
.start
; j
<zoomed
.end
; j
++) {
167 i
= (GLint
) (j
* xscale
);
168 if (i
<0) i
= n
+ i
- 1;
169 COPY_CHAN4(zoomed
.color
.rgba
[j
], rgba
[i
]);
170 zoomed
.zArray
[j
] = z
[i
];
172 if (fog
&& ctx
->Fog
.Enabled
) {
173 for (j
=zoomed
.start
; j
<zoomed
.end
; j
++) {
174 i
= (GLint
) (j
* xscale
);
175 if (i
<0) i
= n
+ i
- 1;
176 zoomed
.fogArray
[j
] = fog
[i
];
181 zoomed
.arrayMask
|= SPAN_Z
;
183 zoomed
.arrayMask
|= SPAN_FOG
;
186 for (zoomed
.y
= r0
; zoomed
.y
< r1
; zoomed
.y
++) {
188 ASSERT((zoomed
.interpMask
& SPAN_RGBA
) == 0);
189 _mesa_write_rgba_span(ctx
, &zoomed
, GL_BITMAP
);
190 RESTORE_SPAN(zoomed
);
191 /* problem here: "zoomed" can change inside
192 "_mesa_write_rgba_span". Best solution: make copy "tmpspan"
193 and give to function, but too slow */
200 _mesa_write_zoomed_rgb_span( GLcontext
*ctx
,
201 GLuint n
, GLint x
, GLint y
, const GLdepth z
[],
203 CONST GLchan rgb
[][3], GLint y0
)
206 GLint r0
, r1
, row
, r
;
208 GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
209 struct sw_span zoomed
;
212 zoomed
.arrayMask
|= SPAN_RGBA
;
214 if (fog
&& ctx
->Fog
.Enabled
)
215 zoomed
.arrayMask
|= SPAN_FOG
;
218 /* compute width of output row */
219 m
= (GLint
) ABSF( n
* ctx
->Pixel
.ZoomX
);
223 if (ctx
->Pixel
.ZoomX
<0.0) {
224 /* adjust x coordinate for left/right mirroring */
228 /* compute which rows to draw */
230 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
231 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
241 /* return early if r0...r1 is above or below window */
246 if (r0
>=ctx
->DrawBuffer
->Height
&& r1
>=ctx
->DrawBuffer
->Height
) {
251 /* check if left edge is outside window */
257 /* make sure span isn't too long or short */
265 ASSERT( m
<= MAX_WIDTH
);
267 /* zoom the span horizontally */
268 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
271 i
= n
- (j
+skipcol
) - 1;
272 zoomed
.color
.rgba
[j
][0] = rgb
[i
][0];
273 zoomed
.color
.rgba
[j
][1] = rgb
[i
][1];
274 zoomed
.color
.rgba
[j
][2] = rgb
[i
][2];
275 zoomed
.color
.rgba
[j
][3] = CHAN_MAX
;
276 zoomed
.zArray
[j
] = z
[i
];
278 if (zoomed
.arrayMask
& SPAN_FOG
) {
280 i
= n
- (j
+skipcol
) - 1;
281 zoomed
.fogArray
[j
] = fog
[i
];
286 GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
288 i
= (GLint
) ((j
+skipcol
) * xscale
);
289 if (i
<0) i
= n
+ i
- 1;
290 zoomed
.color
.rgba
[j
][0] = rgb
[i
][0];
291 zoomed
.color
.rgba
[j
][1] = rgb
[i
][1];
292 zoomed
.color
.rgba
[j
][2] = rgb
[i
][2];
293 zoomed
.color
.rgba
[j
][3] = CHAN_MAX
;
294 zoomed
.zArray
[j
] = z
[i
];
296 if (zoomed
.arrayMask
& SPAN_FOG
) {
298 i
= (GLint
) ((j
+skipcol
) * xscale
);
299 if (i
<0) i
= n
+ i
- 1;
300 zoomed
.fogArray
[j
] = fog
[i
];
306 for (r
=r0
; r
<r1
; r
++) {
307 zoomed
.x
= x
+ skipcol
;
310 ASSERT((zoomed
.interpMask
& SPAN_RGBA
) == 0);
311 _mesa_write_rgba_span( ctx
, &zoomed
, GL_BITMAP
);
318 * As above, but write CI pixels.
321 _mesa_write_zoomed_index_span( GLcontext
*ctx
,
322 GLuint n
, GLint x
, GLint y
, const GLdepth z
[],
324 const GLuint indexes
[], GLint y0
)
327 GLint r0
, r1
, row
, r
;
329 GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
330 struct sw_span zoomed
;
333 zoomed
.arrayMask
|= SPAN_INDEX
;
335 /* compute width of output row */
336 m
= (GLint
) ABSF( n
* ctx
->Pixel
.ZoomX
);
340 if (ctx
->Pixel
.ZoomX
<0.0) {
341 /* adjust x coordinate for left/right mirroring */
345 /* compute which rows to draw */
347 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
348 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
358 /* return early if r0...r1 is above or below window */
363 if (r0
>=ctx
->DrawBuffer
->Height
&& r1
>=ctx
->DrawBuffer
->Height
) {
368 /* check if left edge is outside window */
374 /* make sure span isn't too long or short */
382 ASSERT( m
<= MAX_WIDTH
);
384 /* zoom the span horizontally */
385 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
388 i
= n
- (j
+skipcol
) - 1;
389 zoomed
.color
.index
[j
] = indexes
[i
];
390 zoomed
.zArray
[j
] = z
[i
];
392 if (fog
&& ctx
->Fog
.Enabled
) {
394 i
= n
- (j
+skipcol
) - 1;
395 zoomed
.fogArray
[j
] = fog
[i
];
397 zoomed
.arrayMask
|= SPAN_FOG
;
401 GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
403 i
= (GLint
) ((j
+skipcol
) * xscale
);
404 if (i
<0) i
= n
+ i
- 1;
405 zoomed
.color
.index
[j
] = indexes
[i
];
406 zoomed
.zArray
[j
] = z
[i
];
408 if (fog
&& ctx
->Fog
.Enabled
) {
410 i
= (GLint
) ((j
+skipcol
) * xscale
);
411 if (i
<0) i
= n
+ i
- 1;
412 zoomed
.fogArray
[j
] = fog
[i
];
414 zoomed
.arrayMask
|= SPAN_FOG
;
418 zoomed
.arrayMask
|= SPAN_Z
;
421 for (r
=r0
; r
<r1
; r
++) {
423 ASSERT((zoomed
.interpMask
& SPAN_INDEX
) == 0);
424 zoomed
.x
= x
+ skipcol
;
427 _mesa_write_index_span(ctx
, &zoomed
, GL_BITMAP
);
428 RESTORE_SPAN(zoomed
);
435 * As above, but write stencil values.
438 _mesa_write_zoomed_stencil_span( GLcontext
*ctx
,
439 GLuint n
, GLint x
, GLint y
,
440 const GLstencil stencil
[], GLint y0
)
443 GLint r0
, r1
, row
, r
;
445 GLstencil zstencil
[MAX_WIDTH
]; /* zoomed stencil values */
446 GLint maxwidth
= MIN2( ctx
->DrawBuffer
->Width
, MAX_WIDTH
);
448 /* compute width of output row */
449 m
= (GLint
) ABSF( n
* ctx
->Pixel
.ZoomX
);
453 if (ctx
->Pixel
.ZoomX
<0.0) {
454 /* adjust x coordinate for left/right mirroring */
458 /* compute which rows to draw */
460 r0
= y0
+ (GLint
) (row
* ctx
->Pixel
.ZoomY
);
461 r1
= y0
+ (GLint
) ((row
+1) * ctx
->Pixel
.ZoomY
);
471 /* return early if r0...r1 is above or below window */
476 if (r0
>=ctx
->DrawBuffer
->Height
&& r1
>=ctx
->DrawBuffer
->Height
) {
481 /* check if left edge is outside window */
487 /* make sure span isn't too long or short */
495 ASSERT( m
<= MAX_WIDTH
);
497 /* zoom the span horizontally */
498 if (ctx
->Pixel
.ZoomX
==-1.0F
) {
501 i
= n
- (j
+skipcol
) - 1;
502 zstencil
[j
] = stencil
[i
];
506 GLfloat xscale
= 1.0F
/ ctx
->Pixel
.ZoomX
;
508 i
= (GLint
) ((j
+skipcol
) * xscale
);
509 if (i
<0) i
= n
+ i
- 1;
510 zstencil
[j
] = stencil
[i
];
515 for (r
=r0
; r
<r1
; r
++) {
516 _mesa_write_stencil_span( ctx
, m
, x
+skipcol
, r
, zstencil
);