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