home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / swrast / s_zoom.cpp < prev    next >
C/C++ Source or Header  |  2002-12-06  |  11KB  |  366 lines

  1. /* $Id: s_zoom.c,v 1.19 2002/12/05 04:48:53 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.1
  6.  *
  7.  * Copyright (C) 1999-2002  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. #include "imports.h"
  30. #include "colormac.h"
  31.  
  32. #include "s_context.h"
  33. #include "s_span.h"
  34. #include "s_stencil.h"
  35. #include "s_zoom.h"
  36.  
  37.  
  38. /*
  39.  * Helper function called from _mesa_write_zoomed_rgba/rgb/index_span().
  40.  */
  41. static void
  42. zoom_span( GLcontext *ctx, const struct sw_span *span,
  43.            const GLvoid *src, GLint y0, GLenum format, GLint skipPixels )
  44. {
  45.    GLint r0, r1, row;
  46.    GLint c0, c1, skipCol;
  47.    GLint i, j;
  48.    const GLuint maxWidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
  49.    GLchan rgbaSave[MAX_WIDTH][4];
  50.    GLuint indexSave[MAX_WIDTH];
  51.    const GLchan (*rgba)[4] = (const GLchan (*)[4]) src;
  52.    const GLchan (*rgb)[3] = (const GLchan (*)[3]) src;
  53.    const GLuint *indexes = (const GLuint *) src;
  54.    struct sw_span zoomed;
  55.    struct span_arrays zoomed_arrays;  /* this is big! */
  56.  
  57.    /* no pixel arrays! */
  58.    ASSERT((span->arrayMask & SPAN_XY) == 0);
  59.    ASSERT(span->primitive == GL_BITMAP);
  60.  
  61.    INIT_SPAN(zoomed, GL_BITMAP, 0, 0, 0);
  62.    zoomed.array = &zoomed_arrays;
  63.  
  64.    zoomed.z = span->z;
  65.    zoomed.zStep = span->z;
  66.    zoomed.fog = span->fog;
  67.    zoomed.fogStep = span->fogStep;
  68.    if (format == GL_RGBA || format == GL_RGB) {
  69.       zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
  70.       zoomed.arrayMask |= SPAN_RGBA;
  71.    }
  72.    else if (format == GL_COLOR_INDEX) {
  73.       zoomed.interpMask = span->interpMask & ~SPAN_INDEX;
  74.       zoomed.arrayMask |= SPAN_INDEX;
  75.    }
  76.  
  77.    /*
  78.     * Compute which columns to draw: [c0, c1)
  79.     */
  80. #if 0
  81.    c0 = (GLint) span->x;
  82.    c1 = (GLint) (span->x + span->end * ctx->Pixel.ZoomX);
  83. #else
  84.    c0 = (GLint) span->x + skipPixels * ctx->Pixel.ZoomX;
  85.    c1 = (GLint) (span->x + (skipPixels + span->end) * ctx->Pixel.ZoomX);
  86. #endif
  87.    if (c0 == c1) {
  88.       return;
  89.    }
  90.    else if (c1 < c0) {
  91.       /* swap */
  92.       GLint ctmp = c1;
  93.       c1 = c0;
  94.       c0 = ctmp;
  95.    }
  96.    if (c0 < 0) {
  97.       zoomed.x = 0;
  98.       zoomed.start = 0;
  99.       zoomed.end = c1;
  100.       skipCol = -c0;
  101.    }
  102.    else {
  103.       zoomed.x = c0;
  104.       zoomed.start = 0;
  105.       zoomed.end = c1 - c0;
  106.       skipCol = 0;
  107.    }
  108.    if (zoomed.end > maxWidth)
  109.       zoomed.end = maxWidth;
  110.  
  111.    /*
  112.     * Compute which rows to draw: [r0, r1)
  113.     */
  114.    row = span->y - y0;
  115.    r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
  116.    r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
  117.    if (r0 == r1) {
  118.       return;
  119.    }
  120.    else if (r1 < r0) {
  121.       /* swap */
  122.       GLint rtmp = r1;
  123.       r1 = r0;
  124.       r0 = rtmp;
  125.    }
  126.  
  127.    ASSERT(r0 < r1);
  128.    ASSERT(c0 < c1);
  129.  
  130.    /*
  131.     * Trivial clip rejection testing.
  132.     */
  133.    if (r1 < 0) /* below window */
  134.       return;
  135.    if (r0 >= (GLint) ctx->DrawBuffer->Height) /* above window */
  136.       return;
  137.    if (c1 < 0) /* left of window */
  138.       return;
  139.    if (c0 >= (GLint) ctx->DrawBuffer->Width) /* right of window */
  140.       return;
  141.  
  142.    /* zoom the span horizontally */
  143.    if (format == GL_RGBA) {
  144.       if (ctx->Pixel.ZoomX == -1.0F) {
  145.          /* common case */
  146.          for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
  147.             i = span->end - (j + skipCol) - 1;
  148.             COPY_CHAN4(zoomed.array->rgba[j], rgba[i]);
  149.          }
  150.       }
  151.       else {
  152.          /* general solution */
  153.          const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
  154.          for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
  155.             i = (GLint) ((j + skipCol) * xscale);
  156.             if (ctx->Pixel.ZoomX < 0.0) {
  157.                ASSERT(i <= 0);
  158.                i = span->end + i - 1;
  159.             }
  160.             ASSERT(i >= 0);
  161.             ASSERT(i < span->end);
  162.             COPY_CHAN4(zoomed.array->rgba[j], rgba[i]);
  163.          }
  164.       }
  165.    }
  166.    else if (format == GL_RGB) {
  167.       if (ctx->Pixel.ZoomX == -1.0F) {
  168.          /* common case */
  169.          for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
  170.             i = span->end - (j + skipCol) - 1;
  171.             zoomed.array->rgba[j][0] = rgb[i][0];
  172.             zoomed.array->rgba[j][1] = rgb[i][1];
  173.             zoomed.array->rgba[j][2] = rgb[i][2];
  174.             zoomed.array->rgba[j][3] = CHAN_MAX;
  175.          }
  176.       }
  177.       else {
  178.          /* general solution */
  179.          const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
  180.          for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
  181.             i = (GLint) ((j + skipCol) * xscale);
  182.             if (ctx->Pixel.ZoomX < 0.0) {
  183.                ASSERT(i <= 0);
  184.                i = span->end + i - 1;
  185.             }
  186.             ASSERT(i >= 0);
  187.             ASSERT(i < span->end);
  188.             zoomed.array->rgba[j][0] = rgb[i][0];
  189.             zoomed.array->rgba[j][1] = rgb[i][1];
  190.             zoomed.array->rgba[j][2] = rgb[i][2];
  191.             zoomed.array->rgba[j][3] = CHAN_MAX;
  192.          }
  193.       }
  194.    }
  195.    else if (format == GL_COLOR_INDEX) {
  196.       if (ctx->Pixel.ZoomX == -1.0F) {
  197.          /* common case */
  198.          for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
  199.             i = span->end - (j + skipCol) - 1;
  200.             zoomed.array->index[j] = indexes[i];
  201.          }
  202.       }
  203.       else {
  204.          /* general solution */
  205.          const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
  206.          for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) {
  207.             i = (GLint) ((j + skipCol) * xscale);
  208.             if (ctx->Pixel.ZoomX < 0.0) {
  209.                ASSERT(i <= 0);
  210.                i = span->end + i - 1;
  211.             }
  212.             ASSERT(i >= 0);
  213.             ASSERT(i < span->end);
  214.             zoomed.array->index[j] = indexes[i];
  215.          }
  216.       }
  217.    }
  218.  
  219.    /* write the span in rows [r0, r1) */
  220.    if (format == GL_RGBA || format == GL_RGB) {
  221.       /* Writing the span may modify the colors, so make a backup now if we're
  222.        * going to call _mesa_write_zoomed_span() more than once.
  223.        */
  224.       if (r1 - r0 > 1) {
  225.          MEMCPY(rgbaSave, zoomed.array->rgba, zoomed.end * 4 * sizeof(GLchan));
  226.       }
  227.       for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) {
  228.          _mesa_write_rgba_span(ctx, &zoomed);
  229.          if (r1 - r0 > 1) {
  230.             /* restore the colors */
  231.             MEMCPY(zoomed.array->rgba, rgbaSave, zoomed.end*4 * sizeof(GLchan));
  232.          }
  233.       }
  234.    }
  235.    else if (format == GL_COLOR_INDEX) {
  236.       if (r1 - r0 > 1) {
  237.          MEMCPY(indexSave, zoomed.array->index, zoomed.end * sizeof(GLuint));
  238.       }
  239.       for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) {
  240.          _mesa_write_index_span(ctx, &zoomed);
  241.          if (r1 - r0 > 1) {
  242.             /* restore the colors */
  243.             MEMCPY(zoomed.array->index, indexSave, zoomed.end * sizeof(GLuint));
  244.          }
  245.       }
  246.    }
  247. }
  248.  
  249.  
  250. void
  251. _mesa_write_zoomed_rgba_span( GLcontext *ctx, const struct sw_span *span,
  252.                               CONST GLchan rgba[][4], GLint y0,
  253.                               GLint skipPixels )
  254. {
  255.    zoom_span(ctx, span, (const GLvoid *) rgba, y0, GL_RGBA, skipPixels);
  256. }
  257.  
  258.  
  259. void
  260. _mesa_write_zoomed_rgb_span( GLcontext *ctx, const struct sw_span *span,
  261.                              CONST GLchan rgb[][3], GLint y0,
  262.                              GLint skipPixels )
  263. {
  264.    zoom_span(ctx, span, (const GLvoid *) rgb, y0, GL_RGB, skipPixels);
  265. }
  266.  
  267.  
  268. void
  269. _mesa_write_zoomed_index_span( GLcontext *ctx, const struct sw_span *span,
  270.                                GLint y0, GLint skipPixels )
  271. {
  272.   zoom_span(ctx, span, (const GLvoid *) span->array->index, y0,
  273.             GL_COLOR_INDEX, skipPixels);
  274. }
  275.  
  276.  
  277. /*
  278.  * As above, but write stencil values.
  279.  */
  280. void
  281. _mesa_write_zoomed_stencil_span( GLcontext *ctx,
  282.                                  GLuint n, GLint x, GLint y,
  283.                                  const GLstencil stencil[], GLint y0,
  284.                                  GLint skipPixels )
  285. {
  286.    GLint m;
  287.    GLint r0, r1, row, r;
  288.    GLint i, j, skipcol;
  289.    GLstencil zstencil[MAX_WIDTH];  /* zoomed stencil values */
  290.    GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
  291.  
  292.    (void) skipPixels;  /* XXX this shouldn't be ignored */
  293.  
  294.    /* compute width of output row */
  295.    m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
  296.    if (m==0) {
  297.       return;
  298.    }
  299.    if (ctx->Pixel.ZoomX<0.0) {
  300.       /* adjust x coordinate for left/right mirroring */
  301.       x = x - m;
  302.    }
  303.  
  304.    /* compute which rows to draw */
  305.    row = y - y0;
  306.    r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
  307.    r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
  308.    if (r0==r1) {
  309.       return;
  310.    }
  311.    else if (r1<r0) {
  312.       GLint rtmp = r1;
  313.       r1 = r0;
  314.       r0 = rtmp;
  315.    }
  316.  
  317.    /* return early if r0...r1 is above or below window */
  318.    if (r0<0 && r1<0) {
  319.       /* below window */
  320.       return;
  321.    }
  322.    if (r0 >= (GLint) ctx->DrawBuffer->Height &&
  323.        r1 >= (GLint) ctx->DrawBuffer->Height) {
  324.       /* above window */
  325.       return;
  326.    }
  327.  
  328.    /* check if left edge is outside window */
  329.    skipcol = 0;
  330.    if (x<0) {
  331.       skipcol = -x;
  332.       m += x;
  333.    }
  334.    /* make sure span isn't too long or short */
  335.    if (m>maxwidth) {
  336.       m = maxwidth;
  337.    }
  338.    else if (m<=0) {
  339.       return;
  340.    }
  341.  
  342.    ASSERT( m <= MAX_WIDTH );
  343.  
  344.    /* zoom the span horizontally */
  345.    if (ctx->Pixel.ZoomX==-1.0F) {
  346.       /* n==m */
  347.       for (j=0;j<m;j++) {
  348.          i = n - (j+skipcol) - 1;
  349.          zstencil[j] = stencil[i];
  350.       }
  351.    }
  352.    else {
  353.       GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
  354.       for (j=0;j<m;j++) {
  355.          i = (GLint) ((j+skipcol) * xscale);
  356.          if (i<0)  i = n + i - 1;
  357.          zstencil[j] = stencil[i];
  358.       }
  359.    }
  360.  
  361.    /* write the span */
  362.    for (r=r0; r<r1; r++) {
  363.       _mesa_write_stencil_span( ctx, m, x+skipcol, r, zstencil );
  364.    }
  365. }
  366.