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