home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / copypix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  13.8 KB  |  518 lines

  1. /* $Id: copypix.c,v 1.6 1997/07/24 01:24:45 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.4
  6.  * Copyright (C) 1995-1996  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: copypix.c,v $
  26.  * Revision 1.6  1997/07/24 01:24:45  brianp
  27.  * changed precompiled header symbol from PCH to PC_HEADER
  28.  *
  29.  * Revision 1.5  1997/06/20 02:20:04  brianp
  30.  * replaced Current.IntColor with Current.ByteColor
  31.  *
  32.  * Revision 1.4  1997/05/28 03:23:48  brianp
  33.  * added precompiled header (PCH) support
  34.  *
  35.  * Revision 1.3  1996/09/15 14:18:10  brianp
  36.  * now use GLframebuffer and GLvisual
  37.  *
  38.  * Revision 1.2  1996/09/15 01:48:58  brianp
  39.  * removed #define NULL 0
  40.  *
  41.  * Revision 1.1  1996/09/13 01:38:16  brianp
  42.  * Initial revision
  43.  *
  44.  */
  45.  
  46.  
  47. #ifdef PC_HEADER
  48. #include "all.h"
  49. #else
  50. #include <string.h>
  51. #include <stdio.h>
  52. #include "context.h"
  53. #include "copypix.h"
  54. #include "depth.h"
  55. #include "feedback.h"
  56. #include "dlist.h"
  57. #include "macros.h"
  58. #include "pixel.h"
  59. #include "span.h"
  60. #include "stencil.h"
  61. #include "types.h"
  62. #endif
  63.  
  64. #define BOOL_TO_FLOAT(X)        ( (GLfloat)(GLint) (X) )
  65. #define BOOL_TO_DOUBLE(X)        ( (GLdouble)(GLint) (X) )
  66.  
  67.  
  68. static void copy_rgb_pixels( GLcontext* ctx,
  69.                  GLint srcx, GLint srcy, GLint width, GLint height,
  70.                  GLint destx, GLint desty )
  71. {
  72.    DEFARRAY( GLdepth, zspan, MAX_WIDTH );
  73.    DEFARRAY( GLubyte, red, MAX_WIDTH );
  74.    DEFARRAY( GLubyte, green, MAX_WIDTH );
  75.    DEFARRAY( GLubyte, blue, MAX_WIDTH );
  76.    DEFARRAY( GLubyte, alpha, MAX_WIDTH );
  77.    GLboolean scale_or_bias, quick_draw, zoom;
  78.    GLint sy, dy, stepy;
  79.    GLint i, j;
  80.    GLboolean setbuffer;
  81.  
  82.    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  83.       zoom = GL_FALSE;
  84.    }
  85.    else {
  86.       zoom = GL_TRUE;
  87.    }
  88.  
  89.    /* Determine if copy should be done bottom-to-top or top-to-bottom */
  90.    if (srcy<desty) {
  91.       /* top-down  max-to-min */
  92.       sy = srcy + height - 1;
  93.       dy = desty + height - 1;
  94.       stepy = -1;
  95.    }
  96.    else {
  97.       /* bottom-up  min-to-max */
  98.       sy = srcy;
  99.       dy = desty;
  100.       stepy = 1;
  101.    }
  102.  
  103.    scale_or_bias = ctx->Pixel.RedScale!=1.0 || ctx->Pixel.RedBias!=0.0
  104.         || ctx->Pixel.GreenScale!=1.0 || ctx->Pixel.GreenBias!=0.0
  105.         || ctx->Pixel.BlueScale!=1.0 || ctx->Pixel.BlueBias!=0.0
  106.         || ctx->Pixel.AlphaScale!=1.0 || ctx->Pixel.AlphaBias!=0.0;
  107.  
  108.    if (ctx->Depth.Test) {
  109.       /* fill in array of z values */
  110.       GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
  111.       for (i=0;i<width;i++) {
  112.      zspan[i] = z;
  113.       }
  114.    }
  115.  
  116.    if (ctx->RasterMask==0 && !zoom
  117.        && destx>=0 && destx+width<=ctx->Buffer->Width) {
  118.       quick_draw = GL_TRUE;
  119.    }
  120.    else {
  121.       quick_draw = GL_FALSE;
  122.    }
  123.  
  124.    /* If read and draw buffer are different we must do buffer switching */
  125.    setbuffer = ctx->Pixel.ReadBuffer!=ctx->Color.DrawBuffer;
  126.  
  127.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  128.       /* read */
  129.  
  130.       if (setbuffer) {
  131.      (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  132.       }
  133.       gl_read_color_span( ctx, width, srcx, sy, red, green, blue, alpha );
  134.  
  135.       if (scale_or_bias) {
  136.      GLfloat rbias = ctx->Pixel.RedBias   * ctx->Visual->RedScale;
  137.      GLfloat gbias = ctx->Pixel.GreenBias * ctx->Visual->GreenScale;
  138.      GLfloat bbias = ctx->Pixel.BlueBias  * ctx->Visual->BlueScale;
  139.      GLfloat abias = ctx->Pixel.AlphaBias * ctx->Visual->AlphaScale;
  140.      GLint rmax = (GLint) ctx->Visual->RedScale;
  141.      GLint gmax = (GLint) ctx->Visual->GreenScale;
  142.      GLint bmax = (GLint) ctx->Visual->BlueScale;
  143.      GLint amax = (GLint) ctx->Visual->AlphaScale;
  144.      for (i=0;i<width;i++) {
  145.         GLint r = red[i]   * ctx->Pixel.RedScale   + rbias;
  146.         GLint g = green[i] * ctx->Pixel.GreenScale + gbias;
  147.         GLint b = blue[i]  * ctx->Pixel.BlueScale  + bbias;
  148.         GLint a = alpha[i] * ctx->Pixel.AlphaScale + abias;
  149.         red[i]   = CLAMP( r, 0, rmax );
  150.         green[i] = CLAMP( g, 0, gmax );
  151.         blue[i]  = CLAMP( b, 0, bmax );
  152.         alpha[i] = CLAMP( a, 0, amax );
  153.      }
  154.       }
  155.  
  156.       if (ctx->Pixel.MapColorFlag) {
  157.      GLfloat r = (ctx->Pixel.MapRtoRsize-1) * ctx->Visual->InvRedScale;
  158.      GLfloat g = (ctx->Pixel.MapGtoGsize-1) * ctx->Visual->InvGreenScale;
  159.      GLfloat b = (ctx->Pixel.MapBtoBsize-1) * ctx->Visual->InvBlueScale;
  160.      GLfloat a = (ctx->Pixel.MapAtoAsize-1) * ctx->Visual->InvAlphaScale;
  161.      for (i=0;i<width;i++) {
  162.         GLint ir = red[i] * r;
  163.         GLint ig = green[i] * g;
  164.         GLint ib = blue[i] * b;
  165.         GLint ia = alpha[i] * a;
  166.         red[i]   = (GLint) (ctx->Pixel.MapRtoR[ir]*ctx->Visual->RedScale);
  167.         green[i] = (GLint) (ctx->Pixel.MapGtoG[ig]*ctx->Visual->GreenScale);
  168.         blue[i]  = (GLint) (ctx->Pixel.MapBtoB[ib]*ctx->Visual->BlueScale);
  169.         alpha[i] = (GLint) (ctx->Pixel.MapAtoA[ia]*ctx->Visual->AlphaScale);
  170.      }
  171.       }
  172.  
  173.       /* write */
  174.       if (setbuffer) {
  175.      (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  176.       }
  177.       if (quick_draw && dy>=0 && dy<ctx->Buffer->Height) {
  178.      (*ctx->Driver.WriteColorSpan)( ctx, width, destx, dy,
  179.                  red, green, blue, alpha, NULL);
  180.       }
  181.       else if (zoom) {
  182.      gl_write_zoomed_color_span( ctx, width, destx, dy, zspan,
  183.                      red, green, blue, alpha, desty );
  184.       }
  185.       else {
  186.      gl_write_color_span( ctx, width, destx, dy, zspan,
  187.                   red, green, blue, alpha, GL_BITMAP );
  188.       }
  189.    }
  190.    UNDEFARRAY( zspan );
  191.    UNDEFARRAY( red );
  192.    UNDEFARRAY( green );
  193.    UNDEFARRAY( blue );
  194.    UNDEFARRAY( alpha );
  195. }
  196.  
  197.  
  198.  
  199. static void copy_ci_pixels( GLcontext* ctx,
  200.                 GLint srcx, GLint srcy, GLint width, GLint height,
  201.                 GLint destx, GLint desty )
  202. {
  203.    GLdepth zspan[MAX_WIDTH];
  204.    GLuint indx[MAX_WIDTH];
  205.    GLint sy, dy, stepy;
  206.    GLint i, j;
  207.    GLboolean setbuffer, zoom;
  208.  
  209.    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  210.       zoom = GL_FALSE;
  211.    }
  212.    else {
  213.       zoom = GL_TRUE;
  214.    }
  215.  
  216.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  217.    if (srcy<desty) {
  218.       /* top-down  max-to-min */
  219.       sy = srcy + height - 1;
  220.       dy = desty + height - 1;
  221.       stepy = -1;
  222.    }
  223.    else {
  224.       /* bottom-up  min-to-max */
  225.       sy = srcy;
  226.       dy = desty;
  227.       stepy = 1;
  228.    }
  229.  
  230.    if (ctx->Depth.Test) {
  231.       /* fill in array of z values */
  232.       GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
  233.       for (i=0;i<width;i++) {
  234.      zspan[i] = z;
  235.       }
  236.    }
  237.  
  238.    /* If read and draw buffer are different we must do buffer switching */
  239.    setbuffer = ctx->Pixel.ReadBuffer!=ctx->Color.DrawBuffer;
  240.  
  241.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  242.       /* read */
  243.       if (setbuffer) {
  244.      (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  245.       }
  246.       gl_read_index_span( ctx, width, srcx, sy, indx );
  247.  
  248.       /* shift, offset */
  249.       if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset) {
  250.      if (ctx->Pixel.IndexShift<0) {
  251.         for (i=0;i<width;i++) {
  252.            indx[i] = (indx[i] >> -ctx->Pixel.IndexShift)
  253.              + ctx->Pixel.IndexOffset;
  254.         }
  255.      }
  256.      else {
  257.         for (i=0;i<width;i++) {
  258.            indx[i] = (indx[i] << ctx->Pixel.IndexShift)
  259.              + ctx->Pixel.IndexOffset;
  260.         }
  261.      }
  262.       }
  263.  
  264.       /* mapping */
  265.       if (ctx->Pixel.MapColorFlag) {
  266.      for (i=0;i<width;i++) {
  267.         if (indx[i] < ctx->Pixel.MapItoIsize) {
  268.            indx[i] = ctx->Pixel.MapItoI[ indx[i] ];
  269.         }
  270.      }
  271.       }
  272.  
  273.       /* write */
  274.       if (setbuffer) {
  275.      (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  276.       }
  277.       if (zoom) {
  278.      gl_write_zoomed_index_span( ctx, width, destx, dy, zspan, indx, desty );
  279.       }
  280.       else {
  281.      gl_write_index_span( ctx, width, destx, dy, zspan, indx, GL_BITMAP );
  282.       }
  283.    }
  284. }
  285.  
  286.  
  287.  
  288. /*
  289.  * TODO: Optimize!!!!
  290.  */
  291. static void copy_depth_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
  292.                    GLint width, GLint height,
  293.                    GLint destx, GLint desty )
  294. {
  295.    GLfloat depth[MAX_WIDTH];
  296.    GLdepth zspan[MAX_WIDTH];
  297.    GLuint indx[MAX_WIDTH];
  298.    GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  299.    GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  300.    GLint sy, dy, stepy;
  301.    GLint i, j;
  302.    GLboolean zoom;
  303.  
  304.    if (!ctx->Buffer->Depth) {
  305.       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  306.       return;
  307.    }
  308.  
  309.    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  310.       zoom = GL_FALSE;
  311.    }
  312.    else {
  313.       zoom = GL_TRUE;
  314.    }
  315.  
  316.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  317.    if (srcy<desty) {
  318.       /* top-down  max-to-min */
  319.       sy = srcy + height - 1;
  320.       dy = desty + height - 1;
  321.       stepy = -1;
  322.    }
  323.    else {
  324.       /* bottom-up  min-to-max */
  325.       sy = srcy;
  326.       dy = desty;
  327.       stepy = 1;
  328.    }
  329.  
  330.    /* setup colors or indexes */
  331.    if (ctx->Visual->RGBAflag) {
  332.       GLubyte r, g, b, a;
  333.       r = ctx->Current.ByteColor[0];
  334.       g = ctx->Current.ByteColor[1];
  335.       b = ctx->Current.ByteColor[2];
  336.       a = ctx->Current.ByteColor[3];
  337.       MEMSET( red,   (int) r, width );
  338.       MEMSET( green, (int) g, width );
  339.       MEMSET( blue,  (int) b, width );
  340.       MEMSET( alpha, (int) a, width );
  341.    }
  342.    else {
  343.       for (i=0;i<width;i++) {
  344.      indx[i] = ctx->Current.Index;
  345.       }
  346.    }
  347.  
  348.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  349.       /* read */
  350.       (*ctx->Driver.ReadDepthSpanFloat)( ctx, width, srcx, sy, depth );
  351.       /* scale, bias, clamp */
  352.       for (i=0;i<width;i++) {
  353.      GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
  354.      zspan[i] = (GLint) (CLAMP( d, 0.0, 1.0 ) * DEPTH_SCALE);
  355.       }
  356.       /* write */
  357.       if (ctx->Visual->RGBAflag) {
  358.      if (zoom) {
  359.         gl_write_zoomed_color_span( ctx, width, destx, dy, zspan,
  360.                     red, green, blue, alpha, desty );
  361.      }
  362.      else {
  363.         gl_write_color_span( ctx, width, destx, dy, zspan,
  364.                  red, green, blue, alpha, GL_BITMAP );
  365.      }
  366.       }
  367.       else {
  368.      if (zoom) {
  369.         gl_write_zoomed_index_span( ctx, width, destx, dy,
  370.                     zspan, indx, desty);
  371.      }
  372.      else {
  373.         gl_write_index_span( ctx, width, destx, dy,
  374.                  zspan, indx, GL_BITMAP );
  375.      }
  376.       }
  377.    }
  378. }
  379.  
  380.  
  381.  
  382. static void copy_stencil_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
  383.                  GLint width, GLint height,
  384.                  GLint destx, GLint desty )
  385. {
  386.    GLubyte stencil[MAX_WIDTH];
  387.    GLint sy, dy, stepy;
  388.    GLint i, j;
  389.    GLboolean zoom;
  390.  
  391.    if (!ctx->Buffer->Stencil) {
  392.       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  393.       return;
  394.    }
  395.  
  396.    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  397.       zoom = GL_FALSE;
  398.    }
  399.    else {
  400.       zoom = GL_TRUE;
  401.    }
  402.  
  403.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  404.    if (srcy<desty) {
  405.       /* top-down  max-to-min */
  406.       sy = srcy + height - 1;
  407.       dy = desty + height - 1;
  408.       stepy = -1;
  409.    }
  410.    else {
  411.       /* bottom-up  min-to-max */
  412.       sy = srcy;
  413.       dy = desty;
  414.       stepy = 1;
  415.    }
  416.  
  417.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  418.       /* read */
  419.       gl_read_stencil_span( ctx, width, srcx, sy, stencil );
  420.       /* shift, offset */
  421.       if (ctx->Pixel.IndexShift<0) {
  422.      for (i=0;i<width;i++) {
  423.         stencil[i] = (stencil[i] >> -ctx->Pixel.IndexShift)
  424.              + ctx->Pixel.IndexOffset;
  425.      }
  426.       }
  427.       else {
  428.      for (i=0;i<width;i++) {
  429.         stencil[i] = (stencil[i] << ctx->Pixel.IndexShift)
  430.              + ctx->Pixel.IndexOffset;
  431.      }
  432.       }
  433.       /* mapping */
  434.       if (ctx->Pixel.MapStencilFlag) {
  435.      for (i=0;i<width;i++) {
  436.         if ((GLint) stencil[i] < ctx->Pixel.MapStoSsize) {
  437.            stencil[i] = ctx->Pixel.MapStoS[ stencil[i] ];
  438.         }
  439.      }
  440.       }
  441.       /* write */
  442.       if (zoom) {
  443.      gl_write_zoomed_stencil_span( ctx, width, destx, dy, stencil, desty );
  444.       }
  445.       else {
  446.      gl_write_stencil_span( ctx, width, destx, dy, stencil );
  447.       }
  448.    }
  449. }
  450.  
  451.  
  452.  
  453.  
  454. void gl_CopyPixels( GLcontext* ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height,
  455.             GLenum type )
  456. {
  457.    GLint destx, desty;
  458.  
  459.    if (INSIDE_BEGIN_END(ctx)) {
  460.       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  461.       return;
  462.    }
  463.  
  464.    if (width<0 || height<0) {
  465.       gl_error( ctx, GL_INVALID_VALUE, "glCopyPixels" );
  466.       return;
  467.    }
  468.  
  469.    if (ctx->NewState) {
  470.       gl_update_state(ctx);
  471.    }
  472.  
  473.    if (ctx->RenderMode==GL_RENDER) {
  474.       /* Destination of copy: */
  475.       if (!ctx->Current.RasterPosValid) {
  476.      return;
  477.       }
  478.       destx = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
  479.       desty = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
  480.  
  481.       if (type==GL_COLOR && ctx->Visual->RGBAflag) {
  482.      copy_rgb_pixels( ctx, srcx, srcy, width, height, destx, desty );
  483.       }
  484.       else if (type==GL_COLOR && !ctx->Visual->RGBAflag) {
  485.      copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
  486.       }
  487.       else if (type==GL_DEPTH) {
  488.      copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
  489.       }
  490.       else if (type==GL_STENCIL) {
  491.      copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
  492.       }
  493.       else {
  494.      gl_error( ctx, GL_INVALID_ENUM, "glCopyPixels" );
  495.       }
  496.    }
  497.    else if (ctx->RenderMode==GL_FEEDBACK) {
  498.       GLfloat color[4];
  499.       color[0] = ctx->Current.ByteColor[0] * ctx->Visual->InvRedScale;
  500.       color[1] = ctx->Current.ByteColor[1] * ctx->Visual->InvGreenScale;
  501.       color[2] = ctx->Current.ByteColor[2] * ctx->Visual->InvBlueScale;
  502.       color[3] = ctx->Current.ByteColor[3] * ctx->Visual->InvAlphaScale;
  503.       FEEDBACK_TOKEN( ctx, BOOL_TO_FLOAT(GL_COPY_PIXEL_TOKEN) );
  504.       gl_feedback_vertex( ctx, ctx->Current.RasterPos[0],
  505.               ctx->Current.RasterPos[1],
  506.               ctx->Current.RasterPos[2],
  507.               ctx->Current.RasterPos[3],
  508.               color, ctx->Current.Index,
  509.               ctx->Current.TexCoord );
  510.    }
  511.    else if (ctx->RenderMode==GL_SELECT) {
  512.       gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
  513.    }
  514.  
  515. }
  516.  
  517.  
  518.