s_zoom.c revision 22144ab7552f0799bcfca506bf4ffa7f70a06649
1/* $Id: s_zoom.c,v 1.4 2001/03/12 00:48:42 gareth 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 */
46void
47_mesa_write_zoomed_rgba_span( GLcontext *ctx,
48                              GLuint n, GLint x, GLint y, const GLdepth z[],
49                              const GLfixed *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   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;
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),
147			  zrgba, GL_BITMAP );
148   }
149}
150
151
152
153void
154_mesa_write_zoomed_rgb_span( GLcontext *ctx,
155                             GLuint n, GLint x, GLint y, const GLdepth z[],
156                             const GLfixed *fog,
157                             CONST GLchan rgb[][3], GLint y0 )
158{
159   GLint m;
160   GLint r0, r1, row, r;
161   GLint i, j, skipcol;
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 );
166
167   /* compute width of output row */
168   m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
169   if (m==0) {
170      return;
171   }
172   if (ctx->Pixel.ZoomX<0.0) {
173      /* adjust x coordinate for left/right mirroring */
174      x = x - m;
175   }
176
177   /* compute which rows to draw */
178   row = y-y0;
179   r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
180   r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
181   if (r0==r1) {
182      return;
183   }
184   else if (r1<r0) {
185      GLint rtmp = r1;
186      r1 = r0;
187      r0 = rtmp;
188   }
189
190   /* return early if r0...r1 is above or below window */
191   if (r0<0 && r1<0) {
192      /* below window */
193      return;
194   }
195   if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
196      /* above window */
197      return;
198   }
199
200   /* check if left edge is outside window */
201   skipcol = 0;
202   if (x<0) {
203      skipcol = -x;
204      m += x;
205   }
206   /* make sure span isn't too long or short */
207   if (m>maxwidth) {
208      m = maxwidth;
209   }
210   else if (m<=0) {
211      return;
212   }
213
214   assert( m <= MAX_WIDTH );
215
216   /* zoom the span horizontally */
217   if (ctx->Pixel.ZoomX==-1.0F) {
218      /* n==m */
219      for (j=0;j<m;j++) {
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;
225         zdepth[j] = z[i];
226      }
227      if (fog && ctx->Fog.Enabled) {
228	 for (j=0;j<m;j++) {
229	    i = n - (j+skipcol) - 1;
230	    zfog[j] = fog[i];
231	 }
232      }
233   }
234   else {
235      GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
236      for (j=0;j<m;j++) {
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;
243         zdepth[j] = z[i];
244      }
245      if (fog && ctx->Fog.Enabled) {
246	 for (j=0;j<m;j++) {
247	    i = (GLint) ((j+skipcol) * xscale);
248	    if (i<0)  i = n + i - 1;
249	    zfog[j] = fog[i];
250	 }
251      }
252   }
253
254   /* write the span */
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 );
258   }
259}
260
261
262
263/*
264 * As above, but write CI pixels.
265 */
266void
267_mesa_write_zoomed_index_span( GLcontext *ctx,
268                               GLuint n, GLint x, GLint y, const GLdepth z[],
269                               const GLfixed *fog,
270                               const GLuint indexes[], GLint y0 )
271{
272   GLint m;
273   GLint r0, r1, row, r;
274   GLint i, j, skipcol;
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 );
279
280   /* compute width of output row */
281   m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
282   if (m==0) {
283      return;
284   }
285   if (ctx->Pixel.ZoomX<0.0) {
286      /* adjust x coordinate for left/right mirroring */
287      x = x - m;
288   }
289
290   /* compute which rows to draw */
291   row = y-y0;
292   r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
293   r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
294   if (r0==r1) {
295      return;
296   }
297   else if (r1<r0) {
298      GLint rtmp = r1;
299      r1 = r0;
300      r0 = rtmp;
301   }
302
303   /* return early if r0...r1 is above or below window */
304   if (r0<0 && r1<0) {
305      /* below window */
306      return;
307   }
308   if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
309      /* above window */
310      return;
311   }
312
313   /* check if left edge is outside window */
314   skipcol = 0;
315   if (x<0) {
316      skipcol = -x;
317      m += x;
318   }
319   /* make sure span isn't too long or short */
320   if (m>maxwidth) {
321      m = maxwidth;
322   }
323   else if (m<=0) {
324      return;
325   }
326
327   assert( m <= MAX_WIDTH );
328
329   /* zoom the span horizontally */
330   if (ctx->Pixel.ZoomX==-1.0F) {
331      /* n==m */
332      for (j=0;j<m;j++) {
333         i = n - (j+skipcol) - 1;
334         zindexes[j] = indexes[i];
335         zdepth[j]   = z[i];
336      }
337      if (fog && ctx->Fog.Enabled) {
338	 for (j=0;j<m;j++) {
339	    i = n - (j+skipcol) - 1;
340	    zfog[j] = fog[i];
341	 }
342      }
343   }
344   else {
345      GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
346      for (j=0;j<m;j++) {
347         i = (GLint) ((j+skipcol) * xscale);
348         if (i<0)  i = n + i - 1;
349         zindexes[j] = indexes[i];
350         zdepth[j] = z[i];
351      }
352      if (fog && ctx->Fog.Enabled) {
353	 for (j=0;j<m;j++) {
354	    i = (GLint) ((j+skipcol) * xscale);
355	    if (i<0)  i = n + i - 1;
356	    zfog[j] = fog[i];
357	 }
358      }
359   }
360
361   /* write the span */
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 );
365   }
366}
367
368
369
370/*
371 * As above, but write stencil values.
372 */
373void
374_mesa_write_zoomed_stencil_span( GLcontext *ctx,
375                                 GLuint n, GLint x, GLint y,
376                                 const GLstencil stencil[], GLint y0 )
377{
378   GLint m;
379   GLint r0, r1, row, r;
380   GLint i, j, skipcol;
381   GLstencil zstencil[MAX_WIDTH];  /* zoomed stencil values */
382   GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
383
384   /* compute width of output row */
385   m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
386   if (m==0) {
387      return;
388   }
389   if (ctx->Pixel.ZoomX<0.0) {
390      /* adjust x coordinate for left/right mirroring */
391      x = x - m;
392   }
393
394   /* compute which rows to draw */
395   row = y-y0;
396   r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
397   r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
398   if (r0==r1) {
399      return;
400   }
401   else if (r1<r0) {
402      GLint rtmp = r1;
403      r1 = r0;
404      r0 = rtmp;
405   }
406
407   /* return early if r0...r1 is above or below window */
408   if (r0<0 && r1<0) {
409      /* below window */
410      return;
411   }
412   if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
413      /* above window */
414      return;
415   }
416
417   /* check if left edge is outside window */
418   skipcol = 0;
419   if (x<0) {
420      skipcol = -x;
421      m += x;
422   }
423   /* make sure span isn't too long or short */
424   if (m>maxwidth) {
425      m = maxwidth;
426   }
427   else if (m<=0) {
428      return;
429   }
430
431   assert( m <= MAX_WIDTH );
432
433   /* zoom the span horizontally */
434   if (ctx->Pixel.ZoomX==-1.0F) {
435      /* n==m */
436      for (j=0;j<m;j++) {
437         i = n - (j+skipcol) - 1;
438         zstencil[j] = stencil[i];
439      }
440   }
441   else {
442      GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
443      for (j=0;j<m;j++) {
444         i = (GLint) ((j+skipcol) * xscale);
445         if (i<0)  i = n + i - 1;
446         zstencil[j] = stencil[i];
447      }
448   }
449
450   /* write the span */
451   for (r=r0; r<r1; r++) {
452      _mesa_write_stencil_span( ctx, m, x+skipcol, r, zstencil );
453   }
454}
455