Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.1
  4.  *
  5.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. #include "main/glheader.h"
  26. #include "main/macros.h"
  27. #include "main/imports.h"
  28. #include "main/colormac.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.  * Compute the bounds of the region resulting from zooming a pixel span.
  38.  * The resulting region will be entirely inside the window/scissor bounds
  39.  * so no additional clipping is needed.
  40.  * \param imageX, imageY  position of the mage being drawn (gl WindowPos)
  41.  * \param spanX, spanY  position of span being drawing
  42.  * \param width  number of pixels in span
  43.  * \param x0, x1  returned X bounds of zoomed region [x0, x1)
  44.  * \param y0, y1  returned Y bounds of zoomed region [y0, y1)
  45.  * \return GL_TRUE if any zoomed pixels visible, GL_FALSE if totally clipped
  46.  */
  47. static GLboolean
  48. compute_zoomed_bounds(struct gl_context *ctx, GLint imageX, GLint imageY,
  49.                       GLint spanX, GLint spanY, GLint width,
  50.                       GLint *x0, GLint *x1, GLint *y0, GLint *y1)
  51. {
  52.    const struct gl_framebuffer *fb = ctx->DrawBuffer;
  53.    GLint c0, c1, r0, r1;
  54.  
  55.    ASSERT(spanX >= imageX);
  56.    ASSERT(spanY >= imageY);
  57.  
  58.    /*
  59.     * Compute destination columns: [c0, c1)
  60.     */
  61.    c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX);
  62.    c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX);
  63.    if (c1 < c0) {
  64.       /* swap */
  65.       GLint tmp = c1;
  66.       c1 = c0;
  67.       c0 = tmp;
  68.    }
  69.    c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax);
  70.    c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax);
  71.    if (c0 == c1) {
  72.       return GL_FALSE; /* no width */
  73.    }
  74.  
  75.    /*
  76.     * Compute destination rows: [r0, r1)
  77.     */
  78.    r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY);
  79.    r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY);
  80.    if (r1 < r0) {
  81.       /* swap */
  82.       GLint tmp = r1;
  83.       r1 = r0;
  84.       r0 = tmp;
  85.    }
  86.    r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax);
  87.    r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax);
  88.    if (r0 == r1) {
  89.       return GL_FALSE; /* no height */
  90.    }
  91.  
  92.    *x0 = c0;
  93.    *x1 = c1;
  94.    *y0 = r0;
  95.    *y1 = r1;
  96.  
  97.    return GL_TRUE;
  98. }
  99.  
  100.  
  101. /**
  102.  * Convert a zoomed x image coordinate back to an unzoomed x coord.
  103.  * 'zx' is screen position of a pixel in the zoomed image, who's left edge
  104.  * is at 'imageX'.
  105.  * return corresponding x coord in the original, unzoomed image.
  106.  * This can use this for unzooming X or Y values.
  107.  */
  108. static INLINE GLint
  109. unzoom_x(GLfloat zoomX, GLint imageX, GLint zx)
  110. {
  111.    /*
  112.    zx = imageX + (x - imageX) * zoomX;
  113.    zx - imageX = (x - imageX) * zoomX;
  114.    (zx - imageX) / zoomX = x - imageX;
  115.    */
  116.    GLint x;
  117.    if (zoomX < 0.0)
  118.       zx++;
  119.    x = imageX + (GLint) ((zx - imageX) / zoomX);
  120.    return x;
  121. }
  122.  
  123.  
  124.  
  125. /**
  126.  * Helper function called from _swrast_write_zoomed_rgba/rgb/
  127.  * index/depth_span().
  128.  */
  129. static void
  130. zoom_span( struct gl_context *ctx, GLint imgX, GLint imgY, const SWspan *span,
  131.            const GLvoid *src, GLenum format )
  132. {
  133.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  134.    SWspan zoomed;
  135.    GLint x0, x1, y0, y1;
  136.    GLint zoomedWidth;
  137.  
  138.    if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end,
  139.                               &x0, &x1, &y0, &y1)) {
  140.       return;  /* totally clipped */
  141.    }
  142.  
  143.    if (!swrast->ZoomedArrays) {
  144.       /* allocate on demand */
  145.       swrast->ZoomedArrays = (SWspanarrays *) CALLOC(sizeof(SWspanarrays));
  146.       if (!swrast->ZoomedArrays)
  147.          return;
  148.    }
  149.  
  150.    zoomedWidth = x1 - x0;
  151.    ASSERT(zoomedWidth > 0);
  152.    ASSERT(zoomedWidth <= MAX_WIDTH);
  153.  
  154.    /* no pixel arrays! must be horizontal spans. */
  155.    ASSERT((span->arrayMask & SPAN_XY) == 0);
  156.    ASSERT(span->primitive == GL_BITMAP);
  157.  
  158.    INIT_SPAN(zoomed, GL_BITMAP);
  159.    zoomed.x = x0;
  160.    zoomed.end = zoomedWidth;
  161.    zoomed.array = swrast->ZoomedArrays;
  162.    zoomed.array->ChanType = span->array->ChanType;
  163.    if (zoomed.array->ChanType == GL_UNSIGNED_BYTE)
  164.       zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8;
  165.    else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT)
  166.       zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16;
  167.    else
  168.       zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[FRAG_ATTRIB_COL0];
  169.  
  170.    COPY_4V(zoomed.attrStart[FRAG_ATTRIB_WPOS], span->attrStart[FRAG_ATTRIB_WPOS]);
  171.    COPY_4V(zoomed.attrStepX[FRAG_ATTRIB_WPOS], span->attrStepX[FRAG_ATTRIB_WPOS]);
  172.    COPY_4V(zoomed.attrStepY[FRAG_ATTRIB_WPOS], span->attrStepY[FRAG_ATTRIB_WPOS]);
  173.  
  174.    zoomed.attrStart[FRAG_ATTRIB_FOGC][0] = span->attrStart[FRAG_ATTRIB_FOGC][0];
  175.    zoomed.attrStepX[FRAG_ATTRIB_FOGC][0] = span->attrStepX[FRAG_ATTRIB_FOGC][0];
  176.    zoomed.attrStepY[FRAG_ATTRIB_FOGC][0] = span->attrStepY[FRAG_ATTRIB_FOGC][0];
  177.  
  178.    if (format == GL_RGBA || format == GL_RGB) {
  179.       /* copy Z info */
  180.       zoomed.z = span->z;
  181.       zoomed.zStep = span->zStep;
  182.       /* we'll generate an array of colorss */
  183.       zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
  184.       zoomed.arrayMask |= SPAN_RGBA;
  185.       zoomed.arrayAttribs |= FRAG_BIT_COL0;  /* we'll produce these values */
  186.       ASSERT(span->arrayMask & SPAN_RGBA);
  187.    }
  188.    else if (format == GL_DEPTH_COMPONENT) {
  189.       /* Copy color info */
  190.       zoomed.red = span->red;
  191.       zoomed.green = span->green;
  192.       zoomed.blue = span->blue;
  193.       zoomed.alpha = span->alpha;
  194.       zoomed.redStep = span->redStep;
  195.       zoomed.greenStep = span->greenStep;
  196.       zoomed.blueStep = span->blueStep;
  197.       zoomed.alphaStep = span->alphaStep;
  198.       /* we'll generate an array of depth values */
  199.       zoomed.interpMask = span->interpMask & ~SPAN_Z;
  200.       zoomed.arrayMask |= SPAN_Z;
  201.       ASSERT(span->arrayMask & SPAN_Z);
  202.    }
  203.    else {
  204.       _mesa_problem(ctx, "Bad format in zoom_span");
  205.       return;
  206.    }
  207.  
  208.    /* zoom the span horizontally */
  209.    if (format == GL_RGBA) {
  210.       if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
  211.          const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src;
  212.          GLint i;
  213.          for (i = 0; i < zoomedWidth; i++) {
  214.             GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
  215.             ASSERT(j >= 0);
  216.             ASSERT(j < (GLint) span->end);
  217.             COPY_4UBV(zoomed.array->rgba8[i], rgba[j]);
  218.          }
  219.       }
  220.       else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
  221.          const GLushort (*rgba)[4] = (const GLushort (*)[4]) src;
  222.          GLint i;
  223.          for (i = 0; i < zoomedWidth; i++) {
  224.             GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
  225.             ASSERT(j >= 0);
  226.             ASSERT(j < (GLint) span->end);
  227.             COPY_4V(zoomed.array->rgba16[i], rgba[j]);
  228.          }
  229.       }
  230.       else {
  231.          const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src;
  232.          GLint i;
  233.          for (i = 0; i < zoomedWidth; i++) {
  234.             GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
  235.             ASSERT(j >= 0);
  236.             ASSERT(j < span->end);
  237.             COPY_4V(zoomed.array->attribs[FRAG_ATTRIB_COL0][i], rgba[j]);
  238.          }
  239.       }
  240.    }
  241.    else if (format == GL_RGB) {
  242.       if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
  243.          const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src;
  244.          GLint i;
  245.          for (i = 0; i < zoomedWidth; i++) {
  246.             GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
  247.             ASSERT(j >= 0);
  248.             ASSERT(j < (GLint) span->end);
  249.             zoomed.array->rgba8[i][0] = rgb[j][0];
  250.             zoomed.array->rgba8[i][1] = rgb[j][1];
  251.             zoomed.array->rgba8[i][2] = rgb[j][2];
  252.             zoomed.array->rgba8[i][3] = 0xff;
  253.          }
  254.       }
  255.       else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
  256.          const GLushort (*rgb)[3] = (const GLushort (*)[3]) src;
  257.          GLint i;
  258.          for (i = 0; i < zoomedWidth; i++) {
  259.             GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
  260.             ASSERT(j >= 0);
  261.             ASSERT(j < (GLint) span->end);
  262.             zoomed.array->rgba16[i][0] = rgb[j][0];
  263.             zoomed.array->rgba16[i][1] = rgb[j][1];
  264.             zoomed.array->rgba16[i][2] = rgb[j][2];
  265.             zoomed.array->rgba16[i][3] = 0xffff;
  266.          }
  267.       }
  268.       else {
  269.          const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src;
  270.          GLint i;
  271.          for (i = 0; i < zoomedWidth; i++) {
  272.             GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
  273.             ASSERT(j >= 0);
  274.             ASSERT(j < span->end);
  275.             zoomed.array->attribs[FRAG_ATTRIB_COL0][i][0] = rgb[j][0];
  276.             zoomed.array->attribs[FRAG_ATTRIB_COL0][i][1] = rgb[j][1];
  277.             zoomed.array->attribs[FRAG_ATTRIB_COL0][i][2] = rgb[j][2];
  278.             zoomed.array->attribs[FRAG_ATTRIB_COL0][i][3] = 1.0F;
  279.          }
  280.       }
  281.    }
  282.    else if (format == GL_DEPTH_COMPONENT) {
  283.       const GLuint *zValues = (const GLuint *) src;
  284.       GLint i;
  285.       for (i = 0; i < zoomedWidth; i++) {
  286.          GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
  287.          ASSERT(j >= 0);
  288.          ASSERT(j < (GLint) span->end);
  289.          zoomed.array->z[i] = zValues[j];
  290.       }
  291.       /* Now, fall into the RGB path below */
  292.       format = GL_RGBA;
  293.    }
  294.  
  295.    /* write the span in rows [r0, r1) */
  296.    if (format == GL_RGBA || format == GL_RGB) {
  297.       /* Writing the span may modify the colors, so make a backup now if we're
  298.        * going to call _swrast_write_zoomed_span() more than once.
  299.        * Also, clipping may change the span end value, so store it as well.
  300.        */
  301.       const GLint end = zoomed.end; /* save */
  302.       GLuint rgbaSave[MAX_WIDTH][4];
  303.       const GLint pixelSize =
  304.          (zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) :
  305.          ((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort)
  306.           : 4 * sizeof(GLfloat));
  307.       if (y1 - y0 > 1) {
  308.          memcpy(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize);
  309.       }
  310.       for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
  311.          _swrast_write_rgba_span(ctx, &zoomed);
  312.          zoomed.end = end;  /* restore */
  313.          if (y1 - y0 > 1) {
  314.             /* restore the colors */
  315.             memcpy(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize);
  316.          }
  317.       }
  318.    }
  319. }
  320.  
  321.  
  322. void
  323. _swrast_write_zoomed_rgba_span(struct gl_context *ctx, GLint imgX, GLint imgY,
  324.                                const SWspan *span, const GLvoid *rgba)
  325. {
  326.    zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA);
  327. }
  328.  
  329.  
  330. void
  331. _swrast_write_zoomed_rgb_span(struct gl_context *ctx, GLint imgX, GLint imgY,
  332.                               const SWspan *span, const GLvoid *rgb)
  333. {
  334.    zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB);
  335. }
  336.  
  337.  
  338. void
  339. _swrast_write_zoomed_depth_span(struct gl_context *ctx, GLint imgX, GLint imgY,
  340.                                 const SWspan *span)
  341. {
  342.    zoom_span(ctx, imgX, imgY, span,
  343.              (const GLvoid *) span->array->z, GL_DEPTH_COMPONENT);
  344. }
  345.  
  346.  
  347. /**
  348.  * Zoom/write stencil values.
  349.  * No per-fragment operations are applied.
  350.  */
  351. void
  352. _swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY,
  353.                                   GLint width, GLint spanX, GLint spanY,
  354.                                   const GLstencil stencil[])
  355. {
  356.    GLstencil zoomedVals[MAX_WIDTH];
  357.    GLint x0, x1, y0, y1, y;
  358.    GLint i, zoomedWidth;
  359.  
  360.    if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
  361.                               &x0, &x1, &y0, &y1)) {
  362.       return;  /* totally clipped */
  363.    }
  364.  
  365.    zoomedWidth = x1 - x0;
  366.    ASSERT(zoomedWidth > 0);
  367.    ASSERT(zoomedWidth <= MAX_WIDTH);
  368.  
  369.    /* zoom the span horizontally */
  370.    for (i = 0; i < zoomedWidth; i++) {
  371.       GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
  372.       ASSERT(j >= 0);
  373.       ASSERT(j < width);
  374.       zoomedVals[i] = stencil[j];
  375.    }
  376.  
  377.    /* write the zoomed spans */
  378.    for (y = y0; y < y1; y++) {
  379.       _swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals);
  380.    }
  381. }
  382.  
  383.  
  384. /**
  385.  * Zoom/write z values (16 or 32-bit).
  386.  * No per-fragment operations are applied.
  387.  */
  388. void
  389. _swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY,
  390.                             GLint width, GLint spanX, GLint spanY,
  391.                             const GLvoid *z)
  392. {
  393.    struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer;
  394.    GLushort zoomedVals16[MAX_WIDTH];
  395.    GLuint zoomedVals32[MAX_WIDTH];
  396.    GLint x0, x1, y0, y1, y;
  397.    GLint i, zoomedWidth;
  398.  
  399.    if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
  400.                               &x0, &x1, &y0, &y1)) {
  401.       return;  /* totally clipped */
  402.    }
  403.  
  404.    zoomedWidth = x1 - x0;
  405.    ASSERT(zoomedWidth > 0);
  406.    ASSERT(zoomedWidth <= MAX_WIDTH);
  407.  
  408.    /* zoom the span horizontally */
  409.    if (rb->DataType == GL_UNSIGNED_SHORT) {
  410.       for (i = 0; i < zoomedWidth; i++) {
  411.          GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
  412.          ASSERT(j >= 0);
  413.          ASSERT(j < width);
  414.          zoomedVals16[i] = ((GLushort *) z)[j];
  415.       }
  416.       z = zoomedVals16;
  417.    }
  418.    else {
  419.       ASSERT(rb->DataType == GL_UNSIGNED_INT);
  420.       for (i = 0; i < zoomedWidth; i++) {
  421.          GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
  422.          ASSERT(j >= 0);
  423.          ASSERT(j < width);
  424.          zoomedVals32[i] = ((GLuint *) z)[j];
  425.       }
  426.       z = zoomedVals32;
  427.    }
  428.  
  429.    /* write the zoomed spans */
  430.    for (y = y0; y < y1; y++) {
  431.       rb->PutRow(ctx, rb, zoomedWidth, x0, y, z, NULL);
  432.    }
  433. }
  434.