1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25b8e80941Smrg#include "main/errors.h"
26848b8605Smrg#include "main/glheader.h"
27848b8605Smrg#include "main/macros.h"
28848b8605Smrg#include "main/imports.h"
29848b8605Smrg#include "main/format_pack.h"
30848b8605Smrg
31848b8605Smrg#include "s_context.h"
32848b8605Smrg#include "s_span.h"
33848b8605Smrg#include "s_stencil.h"
34848b8605Smrg#include "s_zoom.h"
35848b8605Smrg
36848b8605Smrg
37848b8605Smrg/**
38848b8605Smrg * Compute the bounds of the region resulting from zooming a pixel span.
39848b8605Smrg * The resulting region will be entirely inside the window/scissor bounds
40848b8605Smrg * so no additional clipping is needed.
41848b8605Smrg * \param imageX, imageY  position of the mage being drawn (gl WindowPos)
42848b8605Smrg * \param spanX, spanY  position of span being drawing
43848b8605Smrg * \param width  number of pixels in span
44848b8605Smrg * \param x0, x1  returned X bounds of zoomed region [x0, x1)
45848b8605Smrg * \param y0, y1  returned Y bounds of zoomed region [y0, y1)
46848b8605Smrg * \return GL_TRUE if any zoomed pixels visible, GL_FALSE if totally clipped
47848b8605Smrg */
48848b8605Smrgstatic GLboolean
49848b8605Smrgcompute_zoomed_bounds(struct gl_context *ctx, GLint imageX, GLint imageY,
50848b8605Smrg                      GLint spanX, GLint spanY, GLint width,
51848b8605Smrg                      GLint *x0, GLint *x1, GLint *y0, GLint *y1)
52848b8605Smrg{
53848b8605Smrg   const struct gl_framebuffer *fb = ctx->DrawBuffer;
54848b8605Smrg   GLint c0, c1, r0, r1;
55848b8605Smrg
56b8e80941Smrg   assert(spanX >= imageX);
57b8e80941Smrg   assert(spanY >= imageY);
58848b8605Smrg
59848b8605Smrg   /*
60848b8605Smrg    * Compute destination columns: [c0, c1)
61848b8605Smrg    */
62848b8605Smrg   c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX);
63848b8605Smrg   c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX);
64848b8605Smrg   if (c1 < c0) {
65848b8605Smrg      /* swap */
66848b8605Smrg      GLint tmp = c1;
67848b8605Smrg      c1 = c0;
68848b8605Smrg      c0 = tmp;
69848b8605Smrg   }
70848b8605Smrg   c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax);
71848b8605Smrg   c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax);
72848b8605Smrg   if (c0 == c1) {
73848b8605Smrg      return GL_FALSE; /* no width */
74848b8605Smrg   }
75848b8605Smrg
76848b8605Smrg   /*
77848b8605Smrg    * Compute destination rows: [r0, r1)
78848b8605Smrg    */
79848b8605Smrg   r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY);
80848b8605Smrg   r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY);
81848b8605Smrg   if (r1 < r0) {
82848b8605Smrg      /* swap */
83848b8605Smrg      GLint tmp = r1;
84848b8605Smrg      r1 = r0;
85848b8605Smrg      r0 = tmp;
86848b8605Smrg   }
87848b8605Smrg   r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax);
88848b8605Smrg   r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax);
89848b8605Smrg   if (r0 == r1) {
90848b8605Smrg      return GL_FALSE; /* no height */
91848b8605Smrg   }
92848b8605Smrg
93848b8605Smrg   *x0 = c0;
94848b8605Smrg   *x1 = c1;
95848b8605Smrg   *y0 = r0;
96848b8605Smrg   *y1 = r1;
97848b8605Smrg
98848b8605Smrg   return GL_TRUE;
99848b8605Smrg}
100848b8605Smrg
101848b8605Smrg
102848b8605Smrg/**
103848b8605Smrg * Convert a zoomed x image coordinate back to an unzoomed x coord.
104848b8605Smrg * 'zx' is screen position of a pixel in the zoomed image, who's left edge
105848b8605Smrg * is at 'imageX'.
106848b8605Smrg * return corresponding x coord in the original, unzoomed image.
107848b8605Smrg * This can use this for unzooming X or Y values.
108848b8605Smrg */
109848b8605Smrgstatic inline GLint
110848b8605Smrgunzoom_x(GLfloat zoomX, GLint imageX, GLint zx)
111848b8605Smrg{
112848b8605Smrg   /*
113848b8605Smrg   zx = imageX + (x - imageX) * zoomX;
114848b8605Smrg   zx - imageX = (x - imageX) * zoomX;
115848b8605Smrg   (zx - imageX) / zoomX = x - imageX;
116848b8605Smrg   */
117848b8605Smrg   GLint x;
118b8e80941Smrg   if (zoomX < 0.0F)
119848b8605Smrg      zx++;
120848b8605Smrg   x = imageX + (GLint) ((zx - imageX) / zoomX);
121848b8605Smrg   return x;
122848b8605Smrg}
123848b8605Smrg
124848b8605Smrg
125848b8605Smrg
126848b8605Smrg/**
127848b8605Smrg * Helper function called from _swrast_write_zoomed_rgba/rgb/
128848b8605Smrg * index/depth_span().
129848b8605Smrg */
130848b8605Smrgstatic void
131848b8605Smrgzoom_span( struct gl_context *ctx, GLint imgX, GLint imgY, const SWspan *span,
132848b8605Smrg           const GLvoid *src, GLenum format )
133848b8605Smrg{
134848b8605Smrg   SWcontext *swrast = SWRAST_CONTEXT(ctx);
135848b8605Smrg   SWspan zoomed;
136848b8605Smrg   GLint x0, x1, y0, y1;
137848b8605Smrg   GLint zoomedWidth;
138848b8605Smrg
139848b8605Smrg   if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end,
140848b8605Smrg                              &x0, &x1, &y0, &y1)) {
141848b8605Smrg      return;  /* totally clipped */
142848b8605Smrg   }
143848b8605Smrg
144848b8605Smrg   if (!swrast->ZoomedArrays) {
145848b8605Smrg      /* allocate on demand */
146848b8605Smrg      swrast->ZoomedArrays = (SWspanarrays *) calloc(1, sizeof(SWspanarrays));
147848b8605Smrg      if (!swrast->ZoomedArrays)
148848b8605Smrg         return;
149848b8605Smrg   }
150848b8605Smrg
151848b8605Smrg   zoomedWidth = x1 - x0;
152b8e80941Smrg   assert(zoomedWidth > 0);
153b8e80941Smrg   assert(zoomedWidth <= SWRAST_MAX_WIDTH);
154848b8605Smrg
155848b8605Smrg   /* no pixel arrays! must be horizontal spans. */
156b8e80941Smrg   assert((span->arrayMask & SPAN_XY) == 0);
157b8e80941Smrg   assert(span->primitive == GL_BITMAP);
158848b8605Smrg
159848b8605Smrg   INIT_SPAN(zoomed, GL_BITMAP);
160848b8605Smrg   zoomed.x = x0;
161848b8605Smrg   zoomed.end = zoomedWidth;
162848b8605Smrg   zoomed.array = swrast->ZoomedArrays;
163848b8605Smrg   zoomed.array->ChanType = span->array->ChanType;
164848b8605Smrg   if (zoomed.array->ChanType == GL_UNSIGNED_BYTE)
165848b8605Smrg      zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8;
166848b8605Smrg   else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT)
167848b8605Smrg      zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16;
168848b8605Smrg   else
169848b8605Smrg      zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[VARYING_SLOT_COL0];
170848b8605Smrg
171848b8605Smrg   COPY_4V(zoomed.attrStart[VARYING_SLOT_POS], span->attrStart[VARYING_SLOT_POS]);
172848b8605Smrg   COPY_4V(zoomed.attrStepX[VARYING_SLOT_POS], span->attrStepX[VARYING_SLOT_POS]);
173848b8605Smrg   COPY_4V(zoomed.attrStepY[VARYING_SLOT_POS], span->attrStepY[VARYING_SLOT_POS]);
174848b8605Smrg
175848b8605Smrg   zoomed.attrStart[VARYING_SLOT_FOGC][0] = span->attrStart[VARYING_SLOT_FOGC][0];
176848b8605Smrg   zoomed.attrStepX[VARYING_SLOT_FOGC][0] = span->attrStepX[VARYING_SLOT_FOGC][0];
177848b8605Smrg   zoomed.attrStepY[VARYING_SLOT_FOGC][0] = span->attrStepY[VARYING_SLOT_FOGC][0];
178848b8605Smrg
179848b8605Smrg   if (format == GL_RGBA || format == GL_RGB) {
180848b8605Smrg      /* copy Z info */
181848b8605Smrg      zoomed.z = span->z;
182848b8605Smrg      zoomed.zStep = span->zStep;
183848b8605Smrg      /* we'll generate an array of colorss */
184848b8605Smrg      zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
185848b8605Smrg      zoomed.arrayMask |= SPAN_RGBA;
186848b8605Smrg      zoomed.arrayAttribs |= VARYING_BIT_COL0;  /* we'll produce these values */
187b8e80941Smrg      assert(span->arrayMask & SPAN_RGBA);
188848b8605Smrg   }
189848b8605Smrg   else if (format == GL_DEPTH_COMPONENT) {
190848b8605Smrg      /* Copy color info */
191848b8605Smrg      zoomed.red = span->red;
192848b8605Smrg      zoomed.green = span->green;
193848b8605Smrg      zoomed.blue = span->blue;
194848b8605Smrg      zoomed.alpha = span->alpha;
195848b8605Smrg      zoomed.redStep = span->redStep;
196848b8605Smrg      zoomed.greenStep = span->greenStep;
197848b8605Smrg      zoomed.blueStep = span->blueStep;
198848b8605Smrg      zoomed.alphaStep = span->alphaStep;
199848b8605Smrg      /* we'll generate an array of depth values */
200848b8605Smrg      zoomed.interpMask = span->interpMask & ~SPAN_Z;
201848b8605Smrg      zoomed.arrayMask |= SPAN_Z;
202b8e80941Smrg      assert(span->arrayMask & SPAN_Z);
203848b8605Smrg   }
204848b8605Smrg   else {
205848b8605Smrg      _mesa_problem(ctx, "Bad format in zoom_span");
206848b8605Smrg      return;
207848b8605Smrg   }
208848b8605Smrg
209848b8605Smrg   /* zoom the span horizontally */
210848b8605Smrg   if (format == GL_RGBA) {
211848b8605Smrg      if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
212848b8605Smrg         const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src;
213848b8605Smrg         GLint i;
214848b8605Smrg         for (i = 0; i < zoomedWidth; i++) {
215848b8605Smrg            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
216b8e80941Smrg            assert(j >= 0);
217b8e80941Smrg            assert(j < (GLint) span->end);
218848b8605Smrg            COPY_4UBV(zoomed.array->rgba8[i], rgba[j]);
219848b8605Smrg         }
220848b8605Smrg      }
221848b8605Smrg      else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
222848b8605Smrg         const GLushort (*rgba)[4] = (const GLushort (*)[4]) src;
223848b8605Smrg         GLint i;
224848b8605Smrg         for (i = 0; i < zoomedWidth; i++) {
225848b8605Smrg            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
226b8e80941Smrg            assert(j >= 0);
227b8e80941Smrg            assert(j < (GLint) span->end);
228848b8605Smrg            COPY_4V(zoomed.array->rgba16[i], rgba[j]);
229848b8605Smrg         }
230848b8605Smrg      }
231848b8605Smrg      else {
232848b8605Smrg         const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src;
233848b8605Smrg         GLint i;
234848b8605Smrg         for (i = 0; i < zoomedWidth; i++) {
235848b8605Smrg            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
236b8e80941Smrg            assert(j >= 0);
237b8e80941Smrg            assert(j < (GLint) span->end);
238848b8605Smrg            COPY_4V(zoomed.array->attribs[VARYING_SLOT_COL0][i], rgba[j]);
239848b8605Smrg         }
240848b8605Smrg      }
241848b8605Smrg   }
242848b8605Smrg   else if (format == GL_RGB) {
243848b8605Smrg      if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
244848b8605Smrg         const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src;
245848b8605Smrg         GLint i;
246848b8605Smrg         for (i = 0; i < zoomedWidth; i++) {
247848b8605Smrg            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
248b8e80941Smrg            assert(j >= 0);
249b8e80941Smrg            assert(j < (GLint) span->end);
250848b8605Smrg            zoomed.array->rgba8[i][0] = rgb[j][0];
251848b8605Smrg            zoomed.array->rgba8[i][1] = rgb[j][1];
252848b8605Smrg            zoomed.array->rgba8[i][2] = rgb[j][2];
253848b8605Smrg            zoomed.array->rgba8[i][3] = 0xff;
254848b8605Smrg         }
255848b8605Smrg      }
256848b8605Smrg      else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
257848b8605Smrg         const GLushort (*rgb)[3] = (const GLushort (*)[3]) src;
258848b8605Smrg         GLint i;
259848b8605Smrg         for (i = 0; i < zoomedWidth; i++) {
260848b8605Smrg            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
261b8e80941Smrg            assert(j >= 0);
262b8e80941Smrg            assert(j < (GLint) span->end);
263848b8605Smrg            zoomed.array->rgba16[i][0] = rgb[j][0];
264848b8605Smrg            zoomed.array->rgba16[i][1] = rgb[j][1];
265848b8605Smrg            zoomed.array->rgba16[i][2] = rgb[j][2];
266848b8605Smrg            zoomed.array->rgba16[i][3] = 0xffff;
267848b8605Smrg         }
268848b8605Smrg      }
269848b8605Smrg      else {
270848b8605Smrg         const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src;
271848b8605Smrg         GLint i;
272848b8605Smrg         for (i = 0; i < zoomedWidth; i++) {
273848b8605Smrg            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
274b8e80941Smrg            assert(j >= 0);
275b8e80941Smrg            assert(j < (GLint) span->end);
276848b8605Smrg            zoomed.array->attribs[VARYING_SLOT_COL0][i][0] = rgb[j][0];
277848b8605Smrg            zoomed.array->attribs[VARYING_SLOT_COL0][i][1] = rgb[j][1];
278848b8605Smrg            zoomed.array->attribs[VARYING_SLOT_COL0][i][2] = rgb[j][2];
279848b8605Smrg            zoomed.array->attribs[VARYING_SLOT_COL0][i][3] = 1.0F;
280848b8605Smrg         }
281848b8605Smrg      }
282848b8605Smrg   }
283848b8605Smrg   else if (format == GL_DEPTH_COMPONENT) {
284848b8605Smrg      const GLuint *zValues = (const GLuint *) src;
285848b8605Smrg      GLint i;
286848b8605Smrg      for (i = 0; i < zoomedWidth; i++) {
287848b8605Smrg         GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
288b8e80941Smrg         assert(j >= 0);
289b8e80941Smrg         assert(j < (GLint) span->end);
290848b8605Smrg         zoomed.array->z[i] = zValues[j];
291848b8605Smrg      }
292848b8605Smrg      /* Now, fall into the RGB path below */
293848b8605Smrg      format = GL_RGBA;
294848b8605Smrg   }
295848b8605Smrg
296848b8605Smrg   /* write the span in rows [r0, r1) */
297848b8605Smrg   if (format == GL_RGBA || format == GL_RGB) {
298848b8605Smrg      /* Writing the span may modify the colors, so make a backup now if we're
299848b8605Smrg       * going to call _swrast_write_zoomed_span() more than once.
300848b8605Smrg       * Also, clipping may change the span end value, so store it as well.
301848b8605Smrg       */
302848b8605Smrg      const GLint end = zoomed.end; /* save */
303848b8605Smrg      void *rgbaSave;
304848b8605Smrg      const GLint pixelSize =
305848b8605Smrg         (zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) :
306848b8605Smrg         ((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort)
307848b8605Smrg          : 4 * sizeof(GLfloat));
308848b8605Smrg
309848b8605Smrg      rgbaSave = malloc(zoomed.end * pixelSize);
310848b8605Smrg      if (!rgbaSave) {
311848b8605Smrg         return;
312848b8605Smrg      }
313848b8605Smrg
314848b8605Smrg      if (y1 - y0 > 1) {
315848b8605Smrg         memcpy(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize);
316848b8605Smrg      }
317848b8605Smrg      for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
318848b8605Smrg         _swrast_write_rgba_span(ctx, &zoomed);
319848b8605Smrg         zoomed.end = end;  /* restore */
320848b8605Smrg         if (y1 - y0 > 1) {
321848b8605Smrg            /* restore the colors */
322848b8605Smrg            memcpy(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize);
323848b8605Smrg         }
324848b8605Smrg      }
325848b8605Smrg
326848b8605Smrg      free(rgbaSave);
327848b8605Smrg   }
328848b8605Smrg}
329848b8605Smrg
330848b8605Smrg
331848b8605Smrgvoid
332848b8605Smrg_swrast_write_zoomed_rgba_span(struct gl_context *ctx, GLint imgX, GLint imgY,
333848b8605Smrg                               const SWspan *span, const GLvoid *rgba)
334848b8605Smrg{
335848b8605Smrg   zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA);
336848b8605Smrg}
337848b8605Smrg
338848b8605Smrg
339848b8605Smrgvoid
340848b8605Smrg_swrast_write_zoomed_rgb_span(struct gl_context *ctx, GLint imgX, GLint imgY,
341848b8605Smrg                              const SWspan *span, const GLvoid *rgb)
342848b8605Smrg{
343848b8605Smrg   zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB);
344848b8605Smrg}
345848b8605Smrg
346848b8605Smrg
347848b8605Smrgvoid
348848b8605Smrg_swrast_write_zoomed_depth_span(struct gl_context *ctx, GLint imgX, GLint imgY,
349848b8605Smrg                                const SWspan *span)
350848b8605Smrg{
351848b8605Smrg   zoom_span(ctx, imgX, imgY, span,
352848b8605Smrg             (const GLvoid *) span->array->z, GL_DEPTH_COMPONENT);
353848b8605Smrg}
354848b8605Smrg
355848b8605Smrg
356848b8605Smrg/**
357848b8605Smrg * Zoom/write stencil values.
358848b8605Smrg * No per-fragment operations are applied.
359848b8605Smrg */
360848b8605Smrgvoid
361848b8605Smrg_swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY,
362848b8605Smrg                                  GLint width, GLint spanX, GLint spanY,
363848b8605Smrg                                  const GLubyte stencil[])
364848b8605Smrg{
365848b8605Smrg   GLubyte *zoomedVals;
366848b8605Smrg   GLint x0, x1, y0, y1, y;
367848b8605Smrg   GLint i, zoomedWidth;
368848b8605Smrg
369848b8605Smrg   if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
370848b8605Smrg                              &x0, &x1, &y0, &y1)) {
371848b8605Smrg      return;  /* totally clipped */
372848b8605Smrg   }
373848b8605Smrg
374848b8605Smrg   zoomedWidth = x1 - x0;
375b8e80941Smrg   assert(zoomedWidth > 0);
376b8e80941Smrg   assert(zoomedWidth <= SWRAST_MAX_WIDTH);
377848b8605Smrg
378848b8605Smrg   zoomedVals = malloc(zoomedWidth * sizeof(GLubyte));
379848b8605Smrg   if (!zoomedVals)
380848b8605Smrg      return;
381848b8605Smrg
382848b8605Smrg   /* zoom the span horizontally */
383848b8605Smrg   for (i = 0; i < zoomedWidth; i++) {
384848b8605Smrg      GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
385b8e80941Smrg      assert(j >= 0);
386b8e80941Smrg      assert(j < width);
387848b8605Smrg      zoomedVals[i] = stencil[j];
388848b8605Smrg   }
389848b8605Smrg
390848b8605Smrg   /* write the zoomed spans */
391848b8605Smrg   for (y = y0; y < y1; y++) {
392848b8605Smrg      _swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals);
393848b8605Smrg   }
394848b8605Smrg
395848b8605Smrg   free(zoomedVals);
396848b8605Smrg}
397848b8605Smrg
398848b8605Smrg
399848b8605Smrg/**
400848b8605Smrg * Zoom/write 32-bit Z values.
401848b8605Smrg * No per-fragment operations are applied.
402848b8605Smrg */
403848b8605Smrgvoid
404848b8605Smrg_swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY,
405848b8605Smrg                            GLint width, GLint spanX, GLint spanY,
406848b8605Smrg                            const GLuint *zVals)
407848b8605Smrg{
408848b8605Smrg   struct gl_renderbuffer *rb =
409848b8605Smrg      ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
410848b8605Smrg   GLuint *zoomedVals;
411848b8605Smrg   GLint x0, x1, y0, y1, y;
412848b8605Smrg   GLint i, zoomedWidth;
413848b8605Smrg
414848b8605Smrg   if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
415848b8605Smrg                              &x0, &x1, &y0, &y1)) {
416848b8605Smrg      return;  /* totally clipped */
417848b8605Smrg   }
418848b8605Smrg
419848b8605Smrg   zoomedWidth = x1 - x0;
420b8e80941Smrg   assert(zoomedWidth > 0);
421b8e80941Smrg   assert(zoomedWidth <= SWRAST_MAX_WIDTH);
422848b8605Smrg
423848b8605Smrg   zoomedVals = malloc(zoomedWidth * sizeof(GLuint));
424848b8605Smrg   if (!zoomedVals)
425848b8605Smrg      return;
426848b8605Smrg
427848b8605Smrg   /* zoom the span horizontally */
428848b8605Smrg   for (i = 0; i < zoomedWidth; i++) {
429848b8605Smrg      GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
430b8e80941Smrg      assert(j >= 0);
431b8e80941Smrg      assert(j < width);
432848b8605Smrg      zoomedVals[i] = zVals[j];
433848b8605Smrg   }
434848b8605Smrg
435848b8605Smrg   /* write the zoomed spans */
436848b8605Smrg   for (y = y0; y < y1; y++) {
437848b8605Smrg      GLubyte *dst = _swrast_pixel_address(rb, x0, y);
438848b8605Smrg      _mesa_pack_uint_z_row(rb->Format, zoomedWidth, zoomedVals, dst);
439848b8605Smrg   }
440848b8605Smrg
441848b8605Smrg   free(zoomedVals);
442848b8605Smrg}
443