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

  1. /* feedback.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  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. $Id: feedback.c,v 1.12 1995/09/07 14:16:35 brianp Exp $
  26.  
  27. $Log: feedback.c,v $
  28.  * Revision 1.12  1995/09/07  14:16:35  brianp
  29.  * use CC.NewState convention
  30.  *
  31.  * Revision 1.11  1995/07/26  15:03:48  brianp
  32.  * replaced some literals with variables for SunOS 4.x per Asif Khan
  33.  *
  34.  * Revision 1.10  1995/07/21  15:08:49  brianp
  35.  * set feedback buffer count to 0 in glFeedbackBuffer() per Bogdan Sikorski
  36.  *
  37.  * Revision 1.9  1995/06/08  20:52:23  brianp
  38.  * removed HitMin/MaxZ tests from feedback_vertex()
  39.  *
  40.  * Revision 1.8  1995/06/07  19:43:54  brianp
  41.  * glRenderMode() returns -1 if feedback buffer overflows, reset counter to zero
  42.  *
  43.  * Revision 1.7  1995/05/22  21:02:41  brianp
  44.  * Release 1.2
  45.  *
  46.  * Revision 1.6  1995/05/22  17:18:05  brianp
  47.  * undid prev change to WRITE_RECORD due to overflow logic
  48.  *
  49.  * Revision 1.5  1995/05/19  13:26:50  brianp
  50.  * added display list support for selection/name stack functions
  51.  *
  52.  * Revision 1.4  1995/05/12  17:00:43  brianp
  53.  * changed CC.Mode!=0 to INSIDE_BEGIN_END
  54.  *
  55.  * Revision 1.3  1995/04/18  15:48:23  brianp
  56.  * fixed assignment of NULL to function pointers to prevent warnings on Suns
  57.  *
  58.  * Revision 1.2  1995/03/04  19:29:44  brianp
  59.  * 1.1 beta revision
  60.  *
  61.  * Revision 1.1  1995/02/24  14:22:05  brianp
  62.  * Initial revision
  63.  *
  64.  */
  65.  
  66.  
  67. #include "context.h"
  68. #include "feedback.h"
  69. #include "list.h"
  70. #include "macros.h"
  71.  
  72.  
  73.  
  74.  
  75. /**********************************************************************/
  76. /*                              Feedback                              */
  77. /**********************************************************************/
  78.  
  79.  
  80. #define FB_3D        0x01
  81. #define FB_4D        0x02
  82. #define FB_INDEX    0x04
  83. #define FB_COLOR    0x08
  84. #define FB_TEXTURE    0X10
  85.  
  86.  
  87.  
  88. void glFeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer )
  89. {
  90.    if (CC.RenderMode==GL_FEEDBACK || INSIDE_BEGIN_END) {
  91.       gl_error( GL_INVALID_OPERATION, "glFeedbackBuffer" );
  92.       return;
  93.    }
  94.  
  95.    if (size<0) {
  96.       gl_error( GL_INVALID_VALUE, "glFeedbackBuffer" );
  97.    }
  98.  
  99.    switch (type) {
  100.       case GL_2D:
  101.      CC.FeedbackMask = 0;
  102.          CC.FeedbackType = type;
  103.      break;
  104.       case GL_3D:
  105.      CC.FeedbackMask = FB_3D;
  106.          CC.FeedbackType = type;
  107.      break;
  108.       case GL_3D_COLOR:
  109.      CC.FeedbackMask = FB_3D | (CC.RGBAflag ? FB_COLOR : FB_INDEX);
  110.          CC.FeedbackType = type;
  111.      break;
  112.       case GL_3D_COLOR_TEXTURE:
  113.      CC.FeedbackMask = FB_3D | (CC.RGBAflag ? FB_COLOR : FB_INDEX)
  114.                           | FB_TEXTURE;
  115.          CC.FeedbackType = type;
  116.      break;
  117.       case GL_4D_COLOR_TEXTURE:
  118.      CC.FeedbackMask = FB_3D | FB_4D | (CC.RGBAflag ? FB_COLOR : FB_INDEX)
  119.                           | FB_TEXTURE;
  120.          CC.FeedbackType = type;
  121.      break;
  122.       default:
  123.      CC.FeedbackMask = 0;
  124.          gl_error( GL_INVALID_ENUM, "glFeedbackBuffer" );
  125.    }
  126.  
  127.    CC.FeedbackBufferSize = size;
  128.    CC.FeedbackBuffer = buffer;
  129.    CC.FeedbackCount = 0;
  130. }
  131.  
  132.  
  133.  
  134. void gl_passthrough( GLfloat token )
  135. {
  136.    if (INSIDE_BEGIN_END) {
  137.       gl_error( GL_INVALID_OPERATION, "glPassThrough" );
  138.       return;
  139.    }
  140.  
  141.    if (CC.RenderMode==GL_FEEDBACK) {
  142.       APPEND_TOKEN( (GLfloat) GL_PASS_THROUGH_TOKEN );
  143.       APPEND_TOKEN( token );
  144.    }
  145. }
  146.  
  147.  
  148. void glPassThrough( GLfloat token )
  149. {
  150.    if (CC.CompileFlag) {
  151.       gl_save_passthrough( token );
  152.    }
  153.    if (CC.ExecuteFlag) {
  154.       gl_passthrough( token );
  155.    }
  156. }
  157.  
  158.  
  159.  
  160. /*
  161.  * Put a vertex into the feedback buffer.
  162.  */
  163. void gl_feedback_vertex( GLfloat x, GLfloat y, GLfloat z, GLfloat w,
  164.              const GLfloat color[4], GLfloat index,
  165.              const GLfloat texcoord[4] )
  166. {
  167.    APPEND_TOKEN( x );
  168.    APPEND_TOKEN( y );
  169.    if (CC.FeedbackMask & FB_3D) {
  170.       APPEND_TOKEN( z );
  171.    }
  172.    if (CC.FeedbackMask & FB_4D) {
  173.       APPEND_TOKEN( w );
  174.    }
  175.    if (CC.FeedbackMask & FB_INDEX) {
  176.       APPEND_TOKEN( index );
  177.    }
  178.    if (CC.FeedbackMask & FB_COLOR) {
  179.       APPEND_TOKEN( color[0] );
  180.       APPEND_TOKEN( color[1] );
  181.       APPEND_TOKEN( color[2] );
  182.       APPEND_TOKEN( color[3] );
  183.    }
  184.    if (CC.FeedbackMask & FB_TEXTURE) {
  185.       APPEND_TOKEN( texcoord[0] );
  186.       APPEND_TOKEN( texcoord[1] );
  187.       APPEND_TOKEN( texcoord[2] );
  188.       APPEND_TOKEN( texcoord[3] );
  189.    }
  190. }
  191.  
  192.  
  193.  
  194. /**********************************************************************/
  195. /*                              Selection                             */
  196. /**********************************************************************/
  197.  
  198.  
  199. void glSelectBuffer( GLsizei size, GLuint *buffer )
  200. {
  201.    if (INSIDE_BEGIN_END) {
  202.       gl_error( GL_INVALID_OPERATION, "glSelectBuffer" );
  203.    }
  204.    if (CC.RenderMode==GL_SELECT) {
  205.       gl_error( GL_INVALID_OPERATION, "glSelectBuffer" );
  206.    }
  207.    CC.SelectBuffer = buffer;
  208.    CC.SelectBufferSize = size;
  209.    CC.SelectBufferCount = 0;
  210.  
  211.    CC.HitFlag = GL_FALSE;
  212.    CC.HitMinZ = 1.0;
  213.    CC.HitMaxZ = 0.0;
  214. }
  215.  
  216.  
  217. void glInitNames( void )
  218. {
  219.    if (CC.CompileFlag) {
  220.       gl_save_initnames();
  221.    }
  222.    if (CC.ExecuteFlag) {
  223.       if (INSIDE_BEGIN_END) {
  224.      gl_error( GL_INVALID_OPERATION, "glInitNames" );
  225.       }
  226.       CC.NameStackDepth = 0;
  227.       CC.HitFlag = GL_FALSE;
  228.       CC.HitMinZ = 1.0;
  229.       CC.HitMaxZ = 0.0;
  230.    }
  231. }
  232.  
  233.  
  234.  
  235. #define WRITE_RECORD( V )                    \
  236.     if (CC.SelectBufferCount < CC.SelectBufferSize) {    \
  237.        CC.SelectBuffer[CC.SelectBufferCount] = (V);        \
  238.     }                            \
  239.     CC.SelectBufferCount++;
  240.  
  241.  
  242.  
  243. static void write_hit_record( void )
  244. {
  245.    if (CC.SelectBufferCount < CC.SelectBufferSize) {
  246.       GLuint i;
  247.       GLuint zmin, zmax, zscale = (~0u);
  248.  
  249.       /* HitMinZ and HitMaxZ are in [0,1].  Multiply these values by */
  250.       /* 2^32-1 and round to nearest unsigned integer. */
  251.  
  252.       zmin = (GLuint) ((GLfloat) zscale * CC.HitMinZ);
  253.       zmax = (GLuint) ((GLfloat) zscale * CC.HitMaxZ);
  254.  
  255.       WRITE_RECORD( CC.NameStackDepth );
  256.       WRITE_RECORD( zmin );
  257.       WRITE_RECORD( zmax );
  258.       for (i=0;i<CC.NameStackDepth;i++) {
  259.          WRITE_RECORD( CC.NameStack[i] );
  260.       }
  261.  
  262.       CC.SelectHits++;
  263.    }
  264.  
  265.    /* TODO: correct??? */
  266.    CC.HitFlag = GL_FALSE;
  267.    CC.HitMinZ = 1.0;
  268.    CC.HitMaxZ = -1.0;
  269. }
  270.  
  271.  
  272.  
  273. void glLoadName( GLuint name )
  274. {
  275.    if (CC.CompileFlag) {
  276.       gl_save_loadname( name );
  277.    }
  278.    if (CC.ExecuteFlag) {
  279.       if (INSIDE_BEGIN_END) {
  280.      gl_error( GL_INVALID_OPERATION, "glLoadName" );
  281.      return;
  282.       }
  283.       if (CC.RenderMode!=GL_SELECT) {
  284.      return;
  285.       }
  286.       if (CC.NameStackDepth==0) {
  287.      gl_error( GL_INVALID_OPERATION, "glLoadName" );
  288.      return;
  289.       }
  290.       if (CC.HitFlag) {
  291.      write_hit_record();
  292.       }
  293.       if (CC.NameStackDepth<MAX_NAME_STACK_DEPTH) {
  294.      CC.NameStack[CC.NameStackDepth-1] = name;
  295.       }
  296.       else {
  297.      CC.NameStack[MAX_NAME_STACK_DEPTH-1] = name;
  298.       }
  299.    }
  300. }
  301.  
  302.  
  303. void glPushName( GLuint name )
  304. {
  305.    if (CC.CompileFlag) {
  306.       gl_save_pushname( name );
  307.    }
  308.    if (CC.ExecuteFlag) {
  309.       if (INSIDE_BEGIN_END) {
  310.      gl_error( GL_INVALID_OPERATION, "glPushName" );
  311.      return;
  312.       }
  313.       if (CC.RenderMode!=GL_SELECT) {
  314.      return;
  315.       }
  316.       if (CC.HitFlag) {
  317.      write_hit_record();
  318.       }
  319.       if (CC.NameStackDepth<MAX_NAME_STACK_DEPTH) {
  320.      CC.NameStack[CC.NameStackDepth++] = name;
  321.       }
  322.       else {
  323.      gl_error( GL_STACK_OVERFLOW, "glPushName" );
  324.       }
  325.    }
  326. }
  327.  
  328.  
  329. void glPopName( void )
  330. {
  331.    if (CC.CompileFlag) {
  332.       gl_save_popname();
  333.    }
  334.    if (CC.ExecuteFlag) {
  335.       if (INSIDE_BEGIN_END) {
  336.      gl_error( GL_INVALID_OPERATION, "glPopName" );
  337.      return;
  338.       }
  339.       if (CC.RenderMode!=GL_SELECT) {
  340.      return;
  341.       }
  342.       if (CC.HitFlag) {
  343.      write_hit_record();
  344.       }
  345.       if (CC.NameStackDepth>0) {
  346.      CC.NameStackDepth--;
  347.       }
  348.       else {
  349.      gl_error( GL_STACK_UNDERFLOW, "glPopName" );
  350.       }
  351.    }
  352. }
  353.  
  354.  
  355.  
  356. /**********************************************************************/
  357. /*                           Render Mode                              */
  358. /**********************************************************************/
  359.  
  360.  
  361.  
  362. GLint glRenderMode( GLenum mode )
  363. {
  364.    GLint result;
  365.  
  366.    if (INSIDE_BEGIN_END) {
  367.       gl_error( GL_INVALID_OPERATION, "glInitNames" );
  368.    }
  369.  
  370.    switch (CC.RenderMode) {
  371.       case GL_RENDER:
  372.      result = 0;
  373.      break;
  374.       case GL_SELECT:
  375.      if (CC.HitFlag) {
  376.         write_hit_record();
  377.      }
  378.      if (CC.SelectBufferCount > CC.SelectBufferSize) {
  379.         /* overflow */
  380.         result = -1;
  381.      }
  382.      else {
  383.         result = CC.SelectHits;
  384.      }
  385.      CC.SelectBufferCount = 0;
  386.      CC.SelectHits = 0;
  387.      CC.NameStackDepth = 0;
  388.      break;
  389.       case GL_FEEDBACK:
  390.      if (CC.FeedbackCount > CC.FeedbackBufferSize) {
  391.         /* overflow */
  392.         result = -1;
  393.      }
  394.      else {
  395.         result = CC.FeedbackCount;
  396.      }
  397.      CC.FeedbackCount = 0;
  398.      break;
  399.    }
  400.  
  401.    switch (mode) {
  402.       case GL_RENDER:
  403.          break;
  404.       case GL_SELECT:
  405.      if (CC.SelectBufferSize==0) {
  406.         /* haven't called glSelectBuffer yet */
  407.         gl_error( GL_INVALID_OPERATION, "glRenderMode" );
  408.      }
  409.      break;
  410.       case GL_FEEDBACK:
  411.      if (CC.FeedbackBufferSize==0) {
  412.         /* haven't called glFeedbackBuffer yet */
  413.         gl_error( GL_INVALID_OPERATION, "glRenderMode" );
  414.      }
  415.      break;
  416.       default:
  417.      gl_error( GL_INVALID_ENUM, "glRenderMode" );
  418.      return 0;
  419.    }
  420.  
  421.    CC.RenderMode = mode;
  422.    CC.NewState = GL_TRUE;
  423.  
  424.    return result;
  425. }
  426.  
  427.