added missing \'s
[mesa.git] / src / mesa / swrast / s_zoom.c
1 /* $Id: s_zoom.c,v 1.6 2001/05/15 21:30:27 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27 #include "glheader.h"
28 #include "macros.h"
29
30 #include "s_context.h"
31 #include "s_span.h"
32 #include "s_stencil.h"
33 #include "s_zoom.h"
34
35
36
37 /*
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.
45 */
46 void
47 _mesa_write_zoomed_rgba_span( GLcontext *ctx,
48 GLuint n, GLint x, GLint y, const GLdepth z[],
49 const GLfloat *fog,
50 CONST GLchan rgba[][4], GLint y0 )
51 {
52 GLint m;
53 GLint r0, r1, row, r;
54 GLint i, j, skipcol;
55 GLchan zrgba[MAX_WIDTH][4]; /* zoomed pixel colors */
56 GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */
57 GLfloat 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;
61
62 /* compute width of output row */
63 m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
64 if (m==0) {
65 return;
66 }
67 if (ctx->Pixel.ZoomX<0.0) {
68 /* adjust x coordinate for left/right mirroring */
69 x = x - m;
70 }
71
72 /* compute which rows to draw */
73 row = y-y0;
74 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
75 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
76 if (r0==r1) {
77 return;
78 }
79 else if (r1<r0) {
80 GLint rtmp = r1;
81 r1 = r0;
82 r0 = rtmp;
83 }
84
85 /* return early if r0...r1 is above or below window */
86 if (r0<0 && r1<0) {
87 /* below window */
88 return;
89 }
90 if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
91 /* above window */
92 return;
93 }
94
95 /* check if left edge is outside window */
96 skipcol = 0;
97 if (x<0) {
98 skipcol = -x;
99 m += x;
100 }
101 /* make sure span isn't too long or short */
102 if (m>maxwidth) {
103 m = maxwidth;
104 }
105 else if (m<=0) {
106 return;
107 }
108
109 assert( m <= MAX_WIDTH );
110
111 /* zoom the span horizontally */
112 if (ctx->Pixel.ZoomX==-1.0F) {
113 /* n==m */
114 for (j=0;j<m;j++) {
115 i = n - (j+skipcol) - 1;
116 dstRGBA32[j] = srcRGBA32[i];
117 zdepth[j] = z[i];
118 }
119 if (fog && ctx->Fog.Enabled) {
120 for (j=0;j<m;j++) {
121 i = n - (j+skipcol) - 1;
122 zfog[j] = fog[i];
123 }
124 }
125 }
126 else {
127 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
128 for (j=0;j<m;j++) {
129 i = (GLint) ((j+skipcol) * xscale);
130 if (i<0) i = n + i - 1;
131 dstRGBA32[j] = srcRGBA32[i];
132 zdepth[j] = z[i];
133 }
134 if (fog && ctx->Fog.Enabled) {
135 for (j=0;j<m;j++) {
136 i = (GLint) ((j+skipcol) * xscale);
137 if (i<0) i = n + i - 1;
138 zfog[j] = fog[i];
139 }
140 }
141 }
142
143 /* write the span */
144 for (r=r0; r<r1; r++) {
145 _mesa_write_rgba_span( ctx, m, x+skipcol, r, zdepth,
146 (fog ? zfog : 0), zrgba, NULL, GL_BITMAP );
147 }
148 }
149
150
151
152 void
153 _mesa_write_zoomed_rgb_span( GLcontext *ctx,
154 GLuint n, GLint x, GLint y, const GLdepth z[],
155 const GLfloat *fog,
156 CONST GLchan rgb[][3], GLint y0 )
157 {
158 GLint m;
159 GLint r0, r1, row, r;
160 GLint i, j, skipcol;
161 GLchan zrgba[MAX_WIDTH][4]; /* zoomed pixel colors */
162 GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */
163 GLfloat zfog[MAX_WIDTH]; /* zoomed fog values */
164 GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
165
166 /* compute width of output row */
167 m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
168 if (m==0) {
169 return;
170 }
171 if (ctx->Pixel.ZoomX<0.0) {
172 /* adjust x coordinate for left/right mirroring */
173 x = x - m;
174 }
175
176 /* compute which rows to draw */
177 row = y-y0;
178 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
179 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
180 if (r0==r1) {
181 return;
182 }
183 else if (r1<r0) {
184 GLint rtmp = r1;
185 r1 = r0;
186 r0 = rtmp;
187 }
188
189 /* return early if r0...r1 is above or below window */
190 if (r0<0 && r1<0) {
191 /* below window */
192 return;
193 }
194 if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
195 /* above window */
196 return;
197 }
198
199 /* check if left edge is outside window */
200 skipcol = 0;
201 if (x<0) {
202 skipcol = -x;
203 m += x;
204 }
205 /* make sure span isn't too long or short */
206 if (m>maxwidth) {
207 m = maxwidth;
208 }
209 else if (m<=0) {
210 return;
211 }
212
213 assert( m <= MAX_WIDTH );
214
215 /* zoom the span horizontally */
216 if (ctx->Pixel.ZoomX==-1.0F) {
217 /* n==m */
218 for (j=0;j<m;j++) {
219 i = n - (j+skipcol) - 1;
220 zrgba[j][0] = rgb[i][0];
221 zrgba[j][1] = rgb[i][1];
222 zrgba[j][2] = rgb[i][2];
223 zrgba[j][3] = CHAN_MAX;
224 zdepth[j] = z[i];
225 }
226 if (fog && ctx->Fog.Enabled) {
227 for (j=0;j<m;j++) {
228 i = n - (j+skipcol) - 1;
229 zfog[j] = fog[i];
230 }
231 }
232 }
233 else {
234 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
235 for (j=0;j<m;j++) {
236 i = (GLint) ((j+skipcol) * xscale);
237 if (i<0) i = n + i - 1;
238 zrgba[j][0] = rgb[i][0];
239 zrgba[j][1] = rgb[i][1];
240 zrgba[j][2] = rgb[i][2];
241 zrgba[j][3] = CHAN_MAX;
242 zdepth[j] = z[i];
243 }
244 if (fog && ctx->Fog.Enabled) {
245 for (j=0;j<m;j++) {
246 i = (GLint) ((j+skipcol) * xscale);
247 if (i<0) i = n + i - 1;
248 zfog[j] = fog[i];
249 }
250 }
251 }
252
253 /* write the span */
254 for (r=r0; r<r1; r++) {
255 _mesa_write_rgba_span( ctx, m, x+skipcol, r, zdepth,
256 (fog ? zfog : 0), zrgba, NULL, GL_BITMAP );
257 }
258 }
259
260
261
262 /*
263 * As above, but write CI pixels.
264 */
265 void
266 _mesa_write_zoomed_index_span( GLcontext *ctx,
267 GLuint n, GLint x, GLint y, const GLdepth z[],
268 const GLfloat *fog,
269 const GLuint indexes[], GLint y0 )
270 {
271 GLint m;
272 GLint r0, r1, row, r;
273 GLint i, j, skipcol;
274 GLuint zindexes[MAX_WIDTH]; /* zoomed color indexes */
275 GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */
276 GLfloat zfog[MAX_WIDTH]; /* zoomed fog values */
277 GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
278
279 /* compute width of output row */
280 m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
281 if (m==0) {
282 return;
283 }
284 if (ctx->Pixel.ZoomX<0.0) {
285 /* adjust x coordinate for left/right mirroring */
286 x = x - m;
287 }
288
289 /* compute which rows to draw */
290 row = y-y0;
291 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
292 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
293 if (r0==r1) {
294 return;
295 }
296 else if (r1<r0) {
297 GLint rtmp = r1;
298 r1 = r0;
299 r0 = rtmp;
300 }
301
302 /* return early if r0...r1 is above or below window */
303 if (r0<0 && r1<0) {
304 /* below window */
305 return;
306 }
307 if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
308 /* above window */
309 return;
310 }
311
312 /* check if left edge is outside window */
313 skipcol = 0;
314 if (x<0) {
315 skipcol = -x;
316 m += x;
317 }
318 /* make sure span isn't too long or short */
319 if (m>maxwidth) {
320 m = maxwidth;
321 }
322 else if (m<=0) {
323 return;
324 }
325
326 assert( m <= MAX_WIDTH );
327
328 /* zoom the span horizontally */
329 if (ctx->Pixel.ZoomX==-1.0F) {
330 /* n==m */
331 for (j=0;j<m;j++) {
332 i = n - (j+skipcol) - 1;
333 zindexes[j] = indexes[i];
334 zdepth[j] = z[i];
335 }
336 if (fog && ctx->Fog.Enabled) {
337 for (j=0;j<m;j++) {
338 i = n - (j+skipcol) - 1;
339 zfog[j] = fog[i];
340 }
341 }
342 }
343 else {
344 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
345 for (j=0;j<m;j++) {
346 i = (GLint) ((j+skipcol) * xscale);
347 if (i<0) i = n + i - 1;
348 zindexes[j] = indexes[i];
349 zdepth[j] = z[i];
350 }
351 if (fog && ctx->Fog.Enabled) {
352 for (j=0;j<m;j++) {
353 i = (GLint) ((j+skipcol) * xscale);
354 if (i<0) i = n + i - 1;
355 zfog[j] = fog[i];
356 }
357 }
358 }
359
360 /* write the span */
361 for (r=r0; r<r1; r++) {
362 _mesa_write_index_span( ctx, m, x+skipcol, r, zdepth,
363 (fog ? zfog : 0), zindexes, NULL, GL_BITMAP );
364 }
365 }
366
367
368
369 /*
370 * As above, but write stencil values.
371 */
372 void
373 _mesa_write_zoomed_stencil_span( GLcontext *ctx,
374 GLuint n, GLint x, GLint y,
375 const GLstencil stencil[], GLint y0 )
376 {
377 GLint m;
378 GLint r0, r1, row, r;
379 GLint i, j, skipcol;
380 GLstencil zstencil[MAX_WIDTH]; /* zoomed stencil values */
381 GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
382
383 /* compute width of output row */
384 m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
385 if (m==0) {
386 return;
387 }
388 if (ctx->Pixel.ZoomX<0.0) {
389 /* adjust x coordinate for left/right mirroring */
390 x = x - m;
391 }
392
393 /* compute which rows to draw */
394 row = y-y0;
395 r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
396 r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
397 if (r0==r1) {
398 return;
399 }
400 else if (r1<r0) {
401 GLint rtmp = r1;
402 r1 = r0;
403 r0 = rtmp;
404 }
405
406 /* return early if r0...r1 is above or below window */
407 if (r0<0 && r1<0) {
408 /* below window */
409 return;
410 }
411 if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
412 /* above window */
413 return;
414 }
415
416 /* check if left edge is outside window */
417 skipcol = 0;
418 if (x<0) {
419 skipcol = -x;
420 m += x;
421 }
422 /* make sure span isn't too long or short */
423 if (m>maxwidth) {
424 m = maxwidth;
425 }
426 else if (m<=0) {
427 return;
428 }
429
430 assert( m <= MAX_WIDTH );
431
432 /* zoom the span horizontally */
433 if (ctx->Pixel.ZoomX==-1.0F) {
434 /* n==m */
435 for (j=0;j<m;j++) {
436 i = n - (j+skipcol) - 1;
437 zstencil[j] = stencil[i];
438 }
439 }
440 else {
441 GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
442 for (j=0;j<m;j++) {
443 i = (GLint) ((j+skipcol) * xscale);
444 if (i<0) i = n + i - 1;
445 zstencil[j] = stencil[i];
446 }
447 }
448
449 /* write the span */
450 for (r=r0; r<r1; r++) {
451 _mesa_write_stencil_span( ctx, m, x+skipcol, r, zstencil );
452 }
453 }