Subversion Repositories Kolibri OS

Rev

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

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