home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / feedback.cpp < prev    next >
C/C++ Source or Header  |  2002-10-24  |  10KB  |  406 lines

  1. /* $Id: feedback.c,v 1.27 2002/10/24 23:57:20 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. #include "glheader.h"
  29. #include "colormac.h"
  30. #include "context.h"
  31. #include "enums.h"
  32. #include "feedback.h"
  33. #include "macros.h"
  34. #include "mmath.h"
  35. #include "mtypes.h"
  36.  
  37.  
  38.  
  39. #define FB_3D        0x01
  40. #define FB_4D        0x02
  41. #define FB_INDEX    0x04
  42. #define FB_COLOR    0x08
  43. #define FB_TEXTURE    0X10
  44.  
  45.  
  46.  
  47. void
  48. _mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer )
  49. {
  50.    GET_CURRENT_CONTEXT(ctx);
  51.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  52.  
  53.    if (ctx->RenderMode==GL_FEEDBACK) {
  54.       _mesa_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
  55.       return;
  56.    }
  57.    if (size<0) {
  58.       _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
  59.       return;
  60.    }
  61.    if (!buffer) {
  62.       _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
  63.       ctx->Feedback.BufferSize = 0;
  64.       return;
  65.    }
  66.  
  67.    switch (type) {
  68.       case GL_2D:
  69.      ctx->Feedback._Mask = 0;
  70.      break;
  71.       case GL_3D:
  72.      ctx->Feedback._Mask = FB_3D;
  73.      break;
  74.       case GL_3D_COLOR:
  75.      ctx->Feedback._Mask = (FB_3D |
  76.                 (ctx->Visual.rgbMode ? FB_COLOR : FB_INDEX));
  77.      break;
  78.       case GL_3D_COLOR_TEXTURE:
  79.      ctx->Feedback._Mask = (FB_3D |
  80.                 (ctx->Visual.rgbMode ? FB_COLOR : FB_INDEX) |
  81.                 FB_TEXTURE);
  82.      break;
  83.       case GL_4D_COLOR_TEXTURE:
  84.      ctx->Feedback._Mask = (FB_3D | FB_4D |
  85.                 (ctx->Visual.rgbMode ? FB_COLOR : FB_INDEX) |
  86.                 FB_TEXTURE);
  87.      break;
  88.       default:
  89.          _mesa_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
  90.      return;
  91.    }
  92.  
  93.    FLUSH_VERTICES(ctx, _NEW_RENDERMODE); /* Always flush */
  94.    ctx->Feedback.Type = type;
  95.    ctx->Feedback.BufferSize = size;
  96.    ctx->Feedback.Buffer = buffer;
  97.    ctx->Feedback.Count = 0;                  /* Becaues of this. */
  98. }
  99.  
  100.  
  101. void
  102. _mesa_PassThrough( GLfloat token )
  103. {
  104.    GET_CURRENT_CONTEXT(ctx);
  105.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  106.  
  107.    if (ctx->RenderMode==GL_FEEDBACK) {
  108.       FLUSH_VERTICES(ctx, 0);
  109.       FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
  110.       FEEDBACK_TOKEN( ctx, token );
  111.    }
  112. }
  113.  
  114.  
  115.  
  116. /*
  117.  * Put a vertex into the feedback buffer.
  118.  */
  119. void _mesa_feedback_vertex( GLcontext *ctx,
  120.                          const GLfloat win[4],
  121.              const GLfloat color[4],
  122.              GLuint index,
  123.              const GLfloat texcoord[4] )
  124. {
  125.    FEEDBACK_TOKEN( ctx, win[0] );
  126.    FEEDBACK_TOKEN( ctx, win[1] );
  127.    if (ctx->Feedback._Mask & FB_3D) {
  128.       FEEDBACK_TOKEN( ctx, win[2] );
  129.    }
  130.    if (ctx->Feedback._Mask & FB_4D) {
  131.       FEEDBACK_TOKEN( ctx, win[3] );
  132.    }
  133.    if (ctx->Feedback._Mask & FB_INDEX) {
  134.       FEEDBACK_TOKEN( ctx, (GLfloat) index );
  135.    }
  136.    if (ctx->Feedback._Mask & FB_COLOR) {
  137.       FEEDBACK_TOKEN( ctx, color[0] );
  138.       FEEDBACK_TOKEN( ctx, color[1] );
  139.       FEEDBACK_TOKEN( ctx, color[2] );
  140.       FEEDBACK_TOKEN( ctx, color[3] );
  141.    }
  142.    if (ctx->Feedback._Mask & FB_TEXTURE) {
  143.       FEEDBACK_TOKEN( ctx, texcoord[0] );
  144.       FEEDBACK_TOKEN( ctx, texcoord[1] );
  145.       FEEDBACK_TOKEN( ctx, texcoord[2] );
  146.       FEEDBACK_TOKEN( ctx, texcoord[3] );
  147.    }
  148. }
  149.  
  150.  
  151. /**********************************************************************/
  152. /*                              Selection                             */
  153. /**********************************************************************/
  154.  
  155.  
  156. /*
  157.  * NOTE: this function can't be put in a display list.
  158.  */
  159. void
  160. _mesa_SelectBuffer( GLsizei size, GLuint *buffer )
  161. {
  162.    GET_CURRENT_CONTEXT(ctx);
  163.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  164.  
  165.    if (ctx->RenderMode==GL_SELECT) {
  166.       _mesa_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
  167.       return;            /* KW: added return */
  168.    }
  169.  
  170.    FLUSH_VERTICES(ctx, _NEW_RENDERMODE); /* why bother? */
  171.    ctx->Select.Buffer = buffer;
  172.    ctx->Select.BufferSize = size;
  173.    ctx->Select.BufferCount = 0;
  174.    ctx->Select.HitFlag = GL_FALSE;
  175.    ctx->Select.HitMinZ = 1.0;
  176.    ctx->Select.HitMaxZ = 0.0;
  177. }
  178.  
  179.  
  180. #define WRITE_RECORD( CTX, V )                    \
  181.     if (CTX->Select.BufferCount < CTX->Select.BufferSize) {    \
  182.        CTX->Select.Buffer[CTX->Select.BufferCount] = (V);    \
  183.     }                            \
  184.     CTX->Select.BufferCount++;
  185.  
  186.  
  187.  
  188. void _mesa_update_hitflag( GLcontext *ctx, GLfloat z )
  189. {
  190.    ctx->Select.HitFlag = GL_TRUE;
  191.    if (z < ctx->Select.HitMinZ) {
  192.       ctx->Select.HitMinZ = z;
  193.    }
  194.    if (z > ctx->Select.HitMaxZ) {
  195.       ctx->Select.HitMaxZ = z;
  196.    }
  197. }
  198.  
  199.  
  200. static void write_hit_record( GLcontext *ctx )
  201. {
  202.    GLuint i;
  203.    GLuint zmin, zmax, zscale = (~0u);
  204.  
  205.    /* HitMinZ and HitMaxZ are in [0,1].  Multiply these values by */
  206.    /* 2^32-1 and round to nearest unsigned integer. */
  207.  
  208.    assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */
  209.    zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
  210.    zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
  211.  
  212.    WRITE_RECORD( ctx, ctx->Select.NameStackDepth );
  213.    WRITE_RECORD( ctx, zmin );
  214.    WRITE_RECORD( ctx, zmax );
  215.    for (i = 0; i < ctx->Select.NameStackDepth; i++) {
  216.       WRITE_RECORD( ctx, ctx->Select.NameStack[i] );
  217.    }
  218.  
  219.    ctx->Select.Hits++;
  220.    ctx->Select.HitFlag = GL_FALSE;
  221.    ctx->Select.HitMinZ = 1.0;
  222.    ctx->Select.HitMaxZ = -1.0;
  223. }
  224.  
  225.  
  226.  
  227. void
  228. _mesa_InitNames( void )
  229. {
  230.    GET_CURRENT_CONTEXT(ctx);
  231.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  232.  
  233.    /* Record the hit before the HitFlag is wiped out again. */
  234.    if (ctx->RenderMode == GL_SELECT) {
  235.       if (ctx->Select.HitFlag) {
  236.          write_hit_record( ctx );
  237.       }
  238.    }
  239.    ctx->Select.NameStackDepth = 0;
  240.    ctx->Select.HitFlag = GL_FALSE;
  241.    ctx->Select.HitMinZ = 1.0;
  242.    ctx->Select.HitMaxZ = 0.0;
  243.    ctx->NewState |= _NEW_RENDERMODE;
  244. }
  245.  
  246.  
  247.  
  248. void
  249. _mesa_LoadName( GLuint name )
  250. {
  251.    GET_CURRENT_CONTEXT(ctx);
  252.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  253.  
  254.    if (ctx->RenderMode != GL_SELECT) {
  255.       return;
  256.    }
  257.    if (ctx->Select.NameStackDepth == 0) {
  258.       _mesa_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
  259.       return;
  260.    }
  261.  
  262.    FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
  263.  
  264.    if (ctx->Select.HitFlag) {
  265.       write_hit_record( ctx );
  266.    }
  267.    if (ctx->Select.NameStackDepth < MAX_NAME_STACK_DEPTH) {
  268.       ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name;
  269.    }
  270.    else {
  271.       ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name;
  272.    }
  273. }
  274.  
  275.  
  276. void
  277. _mesa_PushName( GLuint name )
  278. {
  279.    GET_CURRENT_CONTEXT(ctx);
  280.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  281.  
  282.    if (ctx->RenderMode != GL_SELECT) {
  283.       return;
  284.    }
  285.  
  286.    FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
  287.    if (ctx->Select.HitFlag) {
  288.       write_hit_record( ctx );
  289.    }
  290.    if (ctx->Select.NameStackDepth >= MAX_NAME_STACK_DEPTH) {
  291.       _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
  292.    }
  293.    else
  294.       ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
  295. }
  296.  
  297.  
  298.  
  299. void
  300. _mesa_PopName( void )
  301. {
  302.    GET_CURRENT_CONTEXT(ctx);
  303.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  304.  
  305.    if (ctx->RenderMode != GL_SELECT) {
  306.       return;
  307.    }
  308.  
  309.    FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
  310.    if (ctx->Select.HitFlag) {
  311.       write_hit_record( ctx );
  312.    }
  313.    if (ctx->Select.NameStackDepth == 0) {
  314.       _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
  315.    }
  316.    else
  317.       ctx->Select.NameStackDepth--;
  318. }
  319.  
  320.  
  321.  
  322. /**********************************************************************/
  323. /*                           Render Mode                              */
  324. /**********************************************************************/
  325.  
  326.  
  327.  
  328. /*
  329.  * NOTE: this function can't be put in a display list.
  330.  */
  331. GLint
  332. _mesa_RenderMode( GLenum mode )
  333. {
  334.    GET_CURRENT_CONTEXT(ctx);
  335.    GLint result;
  336.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
  337.  
  338.    if (MESA_VERBOSE & VERBOSE_API)
  339.       _mesa_debug(ctx, "glRenderMode %s\n", _mesa_lookup_enum_by_nr(mode));
  340.  
  341.    FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
  342.  
  343.    switch (ctx->RenderMode) {
  344.       case GL_RENDER:
  345.      result = 0;
  346.      break;
  347.       case GL_SELECT:
  348.      if (ctx->Select.HitFlag) {
  349.         write_hit_record( ctx );
  350.      }
  351.      if (ctx->Select.BufferCount > ctx->Select.BufferSize) {
  352.         /* overflow */
  353. #ifdef DEBUG
  354.             _mesa_warning(ctx, "Feedback buffer overflow");
  355. #endif
  356.         result = -1;
  357.      }
  358.      else {
  359.         result = ctx->Select.Hits;
  360.      }
  361.      ctx->Select.BufferCount = 0;
  362.      ctx->Select.Hits = 0;
  363.      ctx->Select.NameStackDepth = 0;
  364.      break;
  365.       case GL_FEEDBACK:
  366.      if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
  367.         /* overflow */
  368.         result = -1;
  369.      }
  370.      else {
  371.         result = ctx->Feedback.Count;
  372.      }
  373.      ctx->Feedback.Count = 0;
  374.      break;
  375.       default:
  376.      _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
  377.      return 0;
  378.    }
  379.  
  380.    switch (mode) {
  381.       case GL_RENDER:
  382.          break;
  383.       case GL_SELECT:
  384.      if (ctx->Select.BufferSize==0) {
  385.         /* haven't called glSelectBuffer yet */
  386.         _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  387.      }
  388.      break;
  389.       case GL_FEEDBACK:
  390.      if (ctx->Feedback.BufferSize==0) {
  391.         /* haven't called glFeedbackBuffer yet */
  392.         _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  393.      }
  394.      break;
  395.       default:
  396.      _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
  397.      return 0;
  398.    }
  399.  
  400.    ctx->RenderMode = mode;
  401.    if (ctx->Driver.RenderMode)
  402.       ctx->Driver.RenderMode( ctx, mode );
  403.  
  404.    return result;
  405. }
  406.