home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / copypix.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  16KB  |  586 lines

  1. /* $Id: copypix.c,v 1.23 1996/05/01 15:48:03 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995-1996  Brian Paul  (brianp@ssec.wisc.edu)
  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.23  1996/05/01  15:48:03  brianp
  27.  * replaced gl_read_depth_span() with (*DD.read_depth_span_float)()
  28.  *
  29.  * Revision 1.22  1996/02/26  15:06:42  brianp
  30.  * replaced CC.Current.Color with CC.Current.IntColor
  31.  *
  32.  * Revision 1.21  1996/02/09  22:22:14  brianp
  33.  * removed #include "gamma.h"
  34.  *
  35.  * Revision 1.20  1996/02/06  03:23:54  brianp
  36.  * removed gamma correction code
  37.  *
  38.  * Revision 1.19  1995/12/30  00:48:53  brianp
  39.  * use CC.Current.IntColor
  40.  *
  41.  * Revision 1.18  1995/12/18  17:15:27  brianp
  42.  * replaced MAX_DEPTH with DEPTH_SCALE, use new GLdepth type
  43.  *
  44.  * Revision 1.17  1995/11/03  17:40:29  brianp
  45.  * fixed a varname typo, removed unused variables
  46.  *
  47.  * Revision 1.16  1995/10/19  15:47:12  brianp
  48.  * added gamma support
  49.  *
  50.  * Revision 1.15  1995/10/16  15:25:49  brianp
  51.  * added zooming for stencil drawing/copying
  52.  *
  53.  * Revision 1.14  1995/10/14  16:28:21  brianp
  54.  * added glPixelZoom support
  55.  *
  56.  * Revision 1.13  1995/09/15  18:43:25  brianp
  57.  * broke gl_copypixels into sub-functions
  58.  * directly access DD.write_color_span under the right conditions
  59.  *
  60.  * Revision 1.12  1995/09/07  14:15:52  brianp
  61.  * use CC.NewState convention
  62.  * use DEFARRAY macro for MacIntosh support
  63.  *
  64.  * Revision 1.11  1995/08/04  13:07:28  brianp
  65.  * changed some types involved in scale and bias operation
  66.  *
  67.  * Revision 1.10  1995/07/24  19:00:17  brianp
  68.  * convert real window coords to ints with rounding, not truncating
  69.  * changed calls to CLAMP() to prevent type warnings on Suns
  70.  *
  71.  * Revision 1.9  1995/06/12  15:52:07  brianp
  72.  * renamed from copypixels.c to copypix.c
  73.  *
  74.  * Revision 1.8  1995/06/12  15:38:01  brianp
  75.  * changed color arrays to GLubyte
  76.  * added feedback and selection support
  77.  *
  78.  * Revision 1.7  1995/05/31  14:58:45  brianp
  79.  * check for valid rasterpos, use gl_read_color|index_span()
  80.  *
  81.  * Revision 1.6  1995/05/22  21:02:41  brianp
  82.  * Release 1.2
  83.  *
  84.  * Revision 1.5  1995/05/12  19:24:13  brianp
  85.  * replaced CC.Mode!=0 with INSIDE_BEGIN_END
  86.  *
  87.  * Revision 1.4  1995/04/18  15:47:59  brianp
  88.  * added a cast to prevent warning on Suns
  89.  *
  90.  * Revision 1.3  1995/03/13  20:54:53  brianp
  91.  * added read buffer logic
  92.  *
  93.  * Revision 1.2  1995/03/04  19:29:44  brianp
  94.  * 1.1 beta revision
  95.  *
  96.  * Revision 1.1  1995/02/24  14:20:20  brianp
  97.  * Initial revision
  98.  *
  99.  */
  100.  
  101.  
  102. #include <string.h>
  103. #include "context.h"
  104. #include "dd.h"
  105. #include "depth.h"
  106. #include "feedback.h"
  107. #include "list.h"
  108. #include "macros.h"
  109. #include "pixel.h"
  110. #include "span.h"
  111. #include "stencil.h"
  112.  
  113.  
  114. #ifndef NULL
  115. #  define NULL 0
  116. #endif
  117.  
  118.  
  119.  
  120.  
  121. static void copy_rgb_pixels( GLint srcx, GLint srcy, GLint width, GLint height,
  122.                              GLint destx, GLint desty )
  123. {
  124.    DEFARRAY( GLdepth, zspan, MAX_WIDTH );
  125.    DEFARRAY( GLubyte, red, MAX_WIDTH );
  126.    DEFARRAY( GLubyte, green, MAX_WIDTH );
  127.    DEFARRAY( GLubyte, blue, MAX_WIDTH );
  128.    DEFARRAY( GLubyte, alpha, MAX_WIDTH );
  129.    GLboolean scale_or_bias, quick_draw, zoom;
  130.    GLint sy, dy, stepy;
  131.    GLint i, j;
  132.    GLboolean setbuffer;
  133.  
  134.    if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
  135.       zoom = GL_FALSE;
  136.    }
  137.    else {
  138.       zoom = GL_TRUE;
  139.    }
  140.  
  141.    /* Determine if copy should be done bottom-to-top or top-to-bottom */
  142.    if (srcy<desty) {
  143.       /* top-down  max-to-min */
  144.       sy = srcy + height - 1;
  145.       dy = desty + height - 1;
  146.       stepy = -1;
  147.    }
  148.    else {
  149.       /* bottom-up  min-to-max */
  150.       sy = srcy;
  151.       dy = desty;
  152.       stepy = 1;
  153.    }
  154.  
  155.    scale_or_bias = CC.Pixel.RedScale!=1.0 || CC.Pixel.RedBias!=0.0
  156.                 || CC.Pixel.GreenScale!=1.0 || CC.Pixel.GreenBias!=0.0
  157.         || CC.Pixel.BlueScale!=1.0 || CC.Pixel.BlueBias!=0.0
  158.         || CC.Pixel.AlphaScale!=1.0 || CC.Pixel.AlphaBias!=0.0;
  159.  
  160.    if (CC.Depth.Test) {
  161.       /* fill in array of z values */
  162.       GLint z = (GLint) (CC.Current.RasterPos[2] * DEPTH_SCALE);
  163.       for (i=0;i<width;i++) {
  164.          zspan[i] = z;
  165.       }
  166.    }
  167.  
  168.    if (CC.RasterMask==0 && destx>=0 && destx+width<=CC.BufferWidth && !zoom) {
  169.       quick_draw = GL_TRUE;
  170.    }
  171.    else {
  172.       quick_draw = GL_FALSE;
  173.    }
  174.  
  175.    /* If read and draw buffer are different we must do buffer switching */
  176.    setbuffer = CC.Pixel.ReadBuffer!=CC.Color.DrawBuffer;
  177.  
  178.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  179.       /* read */
  180.  
  181.       if (setbuffer) {
  182.          (*DD.set_buffer)( CC.Pixel.ReadBuffer );
  183.       }
  184.       gl_read_color_span( width, srcx, sy, red, green, blue, alpha );
  185.  
  186.       if (scale_or_bias) {
  187.          GLfloat rbias = CC.Pixel.RedBias   * CC.RedScale;
  188.          GLfloat gbias = CC.Pixel.GreenBias * CC.GreenScale;
  189.          GLfloat bbias = CC.Pixel.BlueBias  * CC.BlueScale;
  190.          GLfloat abias = CC.Pixel.AlphaBias * CC.AlphaScale;
  191.          GLint rmax = (GLint) CC.RedScale;
  192.          GLint gmax = (GLint) CC.GreenScale;
  193.          GLint bmax = (GLint) CC.BlueScale;
  194.          GLint amax = (GLint) CC.AlphaScale;
  195.          for (i=0;i<width;i++) {
  196.             GLint r = red[i]   * CC.Pixel.RedScale   + rbias;
  197.             GLint g = green[i] * CC.Pixel.GreenScale + gbias;
  198.             GLint b = blue[i]  * CC.Pixel.BlueScale  + bbias;
  199.             GLint a = alpha[i] * CC.Pixel.AlphaScale + abias;
  200.             red[i]   = CLAMP( r, 0, rmax );
  201.             green[i] = CLAMP( g, 0, gmax );
  202.             blue[i]  = CLAMP( b, 0, bmax );
  203.             alpha[i] = CLAMP( a, 0, amax );
  204.          }
  205.       }
  206.  
  207.       if (CC.Pixel.MapColorFlag) {
  208.          GLfloat r = (CC.Pixel.MapRtoRsize-1) / CC.RedScale;
  209.          GLfloat g = (CC.Pixel.MapGtoGsize-1) / CC.GreenScale;
  210.          GLfloat b = (CC.Pixel.MapBtoBsize-1) / CC.BlueScale;
  211.          GLfloat a = (CC.Pixel.MapAtoAsize-1) / CC.AlphaScale;
  212.          for (i=0;i<width;i++) {
  213.             GLint ir = red[i] * r;
  214.             GLint ig = green[i] * g;
  215.             GLint ib = blue[i] * b;
  216.             GLint ia = alpha[i] * a;
  217.             red[i]   = (GLint) (CC.Pixel.MapRtoR[ir] * CC.RedScale);
  218.             green[i] = (GLint) (CC.Pixel.MapGtoG[ig] * CC.GreenScale);
  219.             blue[i]  = (GLint) (CC.Pixel.MapBtoB[ib] * CC.BlueScale);
  220.             alpha[i] = (GLint) (CC.Pixel.MapAtoA[ia] * CC.AlphaScale);
  221.          }
  222.       }
  223.  
  224.       /* write */
  225.       if (setbuffer) {
  226.          (*DD.set_buffer)( CC.Color.DrawBuffer );
  227.       }
  228.       if (quick_draw && dy>=0 && dy<CC.BufferHeight) {
  229.          (*DD.write_color_span)( width, destx, dy,
  230.                                  red, green, blue, alpha, NULL);
  231.       }
  232.       else if (zoom) {
  233.          gl_write_zoomed_color_span( width, destx, dy, zspan,
  234.                                      red, green, blue, alpha, desty );
  235.       }
  236.       else {
  237.          gl_write_color_span( width, destx, dy, zspan,
  238.                               red, green, blue, alpha, GL_BITMAP );
  239.       }
  240.    }
  241.    UNDEFARRAY( zspan );
  242.    UNDEFARRAY( red );
  243.    UNDEFARRAY( green );
  244.    UNDEFARRAY( blue );
  245.    UNDEFARRAY( alpha );
  246. }
  247.  
  248.  
  249.  
  250. static void copy_ci_pixels( GLint srcx, GLint srcy, GLint width, GLint height,
  251.                              GLint destx, GLint desty )
  252. {
  253.    GLdepth zspan[MAX_WIDTH];
  254.    GLuint indx[MAX_WIDTH];
  255.    GLint sy, dy, stepy;
  256.    GLint i, j;
  257.    GLboolean setbuffer, zoom;
  258.  
  259.    if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
  260.       zoom = GL_FALSE;
  261.    }
  262.    else {
  263.       zoom = GL_TRUE;
  264.    }
  265.  
  266.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  267.    if (srcy<desty) {
  268.       /* top-down  max-to-min */
  269.       sy = srcy + height - 1;
  270.       dy = desty + height - 1;
  271.       stepy = -1;
  272.    }
  273.    else {
  274.       /* bottom-up  min-to-max */
  275.       sy = srcy;
  276.       dy = desty;
  277.       stepy = 1;
  278.    }
  279.  
  280.    if (CC.Depth.Test) {
  281.       /* fill in array of z values */
  282.       GLint z = (GLint) (CC.Current.RasterPos[2] * DEPTH_SCALE);
  283.       for (i=0;i<width;i++) {
  284.          zspan[i] = z;
  285.       }
  286.    }
  287.  
  288.    /* If read and draw buffer are different we must do buffer switching */
  289.    setbuffer = CC.Pixel.ReadBuffer!=CC.Color.DrawBuffer;
  290.  
  291.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  292.       /* read */
  293.       if (setbuffer) {
  294.          (*DD.set_buffer)( CC.Pixel.ReadBuffer );
  295.       }
  296.       gl_read_index_span( width, srcx, sy, indx );
  297.  
  298.       /* shift, offset */
  299.       if (CC.Pixel.IndexShift || CC.Pixel.IndexOffset) {
  300.          if (CC.Pixel.IndexShift<0) {
  301.             for (i=0;i<width;i++) {
  302.                indx[i] = (indx[i] >> -CC.Pixel.IndexShift)
  303.                          + CC.Pixel.IndexOffset;
  304.             }
  305.          }
  306.          else {
  307.             for (i=0;i<width;i++) {
  308.                indx[i] = (indx[i] << CC.Pixel.IndexShift)
  309.                          + CC.Pixel.IndexOffset;
  310.             }
  311.          }
  312.       }
  313.  
  314.       /* mapping */
  315.       if (CC.Pixel.MapColorFlag) {
  316.          for (i=0;i<width;i++) {
  317.             if (indx[i] < CC.Pixel.MapItoIsize) {
  318.                indx[i] = CC.Pixel.MapItoI[ indx[i] ];
  319.             }
  320.          }
  321.       }
  322.  
  323.       /* write */
  324.       if (setbuffer) {
  325.          (*DD.set_buffer)( CC.Color.DrawBuffer );
  326.       }
  327.       if (zoom) {
  328.          gl_write_zoomed_index_span( width, destx, dy, zspan, indx, desty );
  329.       }
  330.       else {
  331.          gl_write_index_span( width, destx, dy, zspan, indx, GL_BITMAP );
  332.       }
  333.    }
  334. }
  335.  
  336.  
  337.  
  338. /*
  339.  * TODO: Optimize!!!!
  340.  */
  341. static void copy_depth_pixels( GLint srcx, GLint srcy,
  342.                                GLint width, GLint height,
  343.                                GLint destx, GLint desty )
  344. {
  345.    GLfloat depth[MAX_WIDTH];
  346.    GLdepth zspan[MAX_WIDTH];
  347.    GLuint indx[MAX_WIDTH];
  348.    GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  349.    GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  350.    GLint sy, dy, stepy;
  351.    GLint i, j;
  352.    GLboolean zoom;
  353.  
  354.    if (!CC.DepthBuffer) {
  355.       gl_error( GL_INVALID_OPERATION, "glCopyPixels" );
  356.       return;
  357.    }
  358.  
  359.    if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
  360.       zoom = GL_FALSE;
  361.    }
  362.    else {
  363.       zoom = GL_TRUE;
  364.    }
  365.  
  366.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  367.    if (srcy<desty) {
  368.       /* top-down  max-to-min */
  369.       sy = srcy + height - 1;
  370.       dy = desty + height - 1;
  371.       stepy = -1;
  372.    }
  373.    else {
  374.       /* bottom-up  min-to-max */
  375.       sy = srcy;
  376.       dy = desty;
  377.       stepy = 1;
  378.    }
  379.  
  380.    /* setup colors or indexes */
  381.    if (CC.RGBAflag) {
  382.       GLubyte r, g, b, a;
  383.       r = CC.Current.IntColor[0];
  384.       g = CC.Current.IntColor[1];
  385.       b = CC.Current.IntColor[2];
  386.       a = CC.Current.IntColor[3];
  387.       MEMSET( red,   (int) r, width );
  388.       MEMSET( green, (int) g, width );
  389.       MEMSET( blue,  (int) b, width );
  390.       MEMSET( alpha, (int) a, width );
  391.    }
  392.    else {
  393.       for (i=0;i<width;i++) {
  394.          indx[i] = CC.Current.Index;
  395.       }
  396.    }
  397.  
  398.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  399.       /* read */
  400.       (*DD.read_depth_span_float)( width, srcx, sy, depth );
  401.       /* scale, bias, clamp */
  402.       for (i=0;i<width;i++) {
  403.          GLfloat d = depth[i] * CC.Pixel.DepthScale + CC.Pixel.DepthBias;
  404.          zspan[i] = (GLint) (CLAMP( d, 0.0, 1.0 ) * DEPTH_SCALE);
  405.       }
  406.       /* write */
  407.       if (CC.RGBAflag) {
  408.          if (zoom) {
  409.             gl_write_zoomed_color_span( width, destx, dy, zspan,
  410.                                         red, green, blue, alpha, desty );
  411.          }
  412.          else {
  413.             gl_write_color_span( width, destx, dy, zspan,
  414.                                  red, green, blue, alpha, GL_BITMAP );
  415.          }
  416.       }
  417.       else {
  418.          if (zoom) {
  419.             gl_write_zoomed_index_span( width, destx, dy, zspan, indx, desty);
  420.          }
  421.          else {
  422.             gl_write_index_span( width, destx, dy, zspan, indx, GL_BITMAP );
  423.          }
  424.       }
  425.    }
  426. }
  427.  
  428.  
  429.  
  430. static void copy_stencil_pixels( GLint srcx, GLint srcy,
  431.                                  GLint width, GLint height,
  432.                                  GLint destx, GLint desty )
  433. {
  434.    GLubyte stencil[MAX_WIDTH];
  435.    GLint sy, dy, stepy;
  436.    GLint i, j;
  437.    GLboolean zoom;
  438.  
  439.    if (!CC.StencilBuffer) {
  440.       gl_error( GL_INVALID_OPERATION, "glCopyPixels" );
  441.       return;
  442.    }
  443.  
  444.    if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
  445.       zoom = GL_FALSE;
  446.    }
  447.    else {
  448.       zoom = GL_TRUE;
  449.    }
  450.  
  451.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  452.    if (srcy<desty) {
  453.       /* top-down  max-to-min */
  454.       sy = srcy + height - 1;
  455.       dy = desty + height - 1;
  456.       stepy = -1;
  457.    }
  458.    else {
  459.       /* bottom-up  min-to-max */
  460.       sy = srcy;
  461.       dy = desty;
  462.       stepy = 1;
  463.    }
  464.  
  465.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  466.       /* read */
  467.       gl_read_stencil_span( width, srcx, sy, stencil );
  468.       /* shift, offset */
  469.       if (CC.Pixel.IndexShift<0) {
  470.          for (i=0;i<width;i++) {
  471.             stencil[i] = (stencil[i] >> -CC.Pixel.IndexShift)
  472.                          + CC.Pixel.IndexOffset;
  473.          }
  474.       }
  475.       else {
  476.          for (i=0;i<width;i++) {
  477.             stencil[i] = (stencil[i] << CC.Pixel.IndexShift)
  478.              + CC.Pixel.IndexOffset;
  479.          }
  480.       }
  481.       /* mapping */
  482.       if (CC.Pixel.MapStencilFlag) {
  483.          for (i=0;i<width;i++) {
  484.             if ((GLint) stencil[i] < CC.Pixel.MapStoSsize) {
  485.                stencil[i] = CC.Pixel.MapStoS[ stencil[i] ];
  486.             }
  487.          }
  488.       }
  489.       /* write */
  490.       if (zoom) {
  491.          gl_write_zoomed_stencil_span( width, destx, dy, stencil, desty );
  492.       }
  493.       else {
  494.          gl_write_stencil_span( width, destx, dy, stencil );
  495.       }
  496.    }
  497. }
  498.  
  499.  
  500.  
  501.  
  502. void gl_copypixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
  503.             GLenum type )
  504. {
  505.    GLint destx, desty;
  506.  
  507.    if (INSIDE_BEGIN_END) {
  508.       gl_error( GL_INVALID_OPERATION, "glCopyPixels" );
  509.       return;
  510.    }
  511.  
  512.    if (width<0 || height<0) {
  513.       gl_error( GL_INVALID_VALUE, "glCopyPixels" );
  514.       return;
  515.    }
  516.  
  517.    if (CC.NewState) {
  518.       gl_update_state();
  519.    }
  520.  
  521.    if (CC.RenderMode==GL_RENDER) {
  522.       /* Destination of copy: */
  523.       if (!CC.Current.RasterPosValid) {
  524.      return;
  525.       }
  526.       destx = (GLint) (CC.Current.RasterPos[0] + 0.5F);
  527.       desty = (GLint) (CC.Current.RasterPos[1] + 0.5F);
  528.  
  529.       if (type==GL_COLOR && CC.RGBAflag) {
  530.          copy_rgb_pixels( srcx, srcy, width, height, destx, desty );
  531.       }
  532.       else if (type==GL_COLOR && !CC.RGBAflag) {
  533.          copy_ci_pixels( srcx, srcy, width, height, destx, desty );
  534.       }
  535.       else if (type==GL_DEPTH) {
  536.          copy_depth_pixels( srcx, srcy, width, height, destx, desty );
  537.       }
  538.       else if (type==GL_STENCIL) {
  539.          copy_stencil_pixels( srcx, srcy, width, height, destx, desty );
  540.       }
  541.       else {
  542.      gl_error( GL_INVALID_ENUM, "glCopyPixels" );
  543.       }
  544.    }
  545.    else if (CC.RenderMode==GL_FEEDBACK) {
  546.       GLfloat color[4];
  547.       color[0] = CC.Current.IntColor[0] / CC.RedScale;
  548.       color[1] = CC.Current.IntColor[1] / CC.GreenScale;
  549.       color[2] = CC.Current.IntColor[2] / CC.BlueScale;
  550.       color[3] = CC.Current.IntColor[3] / CC.AlphaScale;
  551.       APPEND_TOKEN( (GLfloat) GL_COPY_PIXEL_TOKEN );
  552.       gl_feedback_vertex( CC.Current.RasterPos[0],
  553.               CC.Current.RasterPos[1],
  554.               CC.Current.RasterPos[2],
  555.               CC.Current.RasterPos[3],
  556.               color, CC.Current.Index,
  557.               CC.Current.TexCoord );
  558.    }
  559.    else if (CC.RenderMode==GL_SELECT) {
  560.       /* TODO: verify that this is correct */
  561.       CC.HitFlag = GL_TRUE;
  562.       if (CC.Current.RasterPos[2] < CC.HitMinZ) {
  563.      CC.HitMinZ = CC.Current.RasterPos[2];
  564.       }
  565.       if (CC.Current.RasterPos[2] > CC.HitMaxZ) {
  566.      CC.HitMaxZ = CC.Current.RasterPos[2];
  567.       }
  568.    }
  569.  
  570. }
  571.  
  572.  
  573.  
  574. void glCopyPixels( GLint x, GLint y, GLsizei width, GLsizei height,
  575.            GLenum type )
  576. {
  577.    if (CC.CompileFlag) {
  578.       gl_save_copypixels( x, y, width, height, type );
  579.    }
  580.    if (CC.ExecuteFlag) {
  581.       gl_copypixels( x, y, width, height, type );
  582.    }
  583. }
  584.  
  585.  
  586.