home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / feedback.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  13KB  |  517 lines

  1. /* $Id: feedback.c,v 1.5 1999/11/08 07:36:44 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  * 
  7.  * Copyright (C) 1999  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.  
  29.  
  30.  
  31. #ifdef PC_HEADER
  32. #include "all.h"
  33. #else
  34. #ifndef XFree86Server
  35. #include <assert.h>
  36. #include <stdio.h>
  37. #else
  38. #include "GL/xf86glx.h"
  39. #endif
  40. #include "context.h"
  41. #include "enums.h"
  42. #include "feedback.h"
  43. #include "macros.h"
  44. #include "mmath.h"
  45. #include "types.h"
  46. #include "triangle.h"
  47. #endif
  48.  
  49.  
  50.  
  51. #define FB_3D        0x01
  52. #define FB_4D        0x02
  53. #define FB_INDEX    0x04
  54. #define FB_COLOR    0x08
  55. #define FB_TEXTURE    0X10
  56.  
  57.  
  58.  
  59. void
  60. gl_FeedbackBuffer( GLcontext *ctx, GLsizei size, GLenum type, GLfloat *buffer )
  61. {
  62.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glFeedbackBuffer" );
  63.  
  64.    if (ctx->RenderMode==GL_FEEDBACK) {
  65.       gl_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
  66.       return;
  67.    }
  68.  
  69.    if (size<0) {
  70.       gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
  71.       return;
  72.    }
  73.    if (!buffer) {
  74.       gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
  75.       ctx->Feedback.BufferSize = 0;
  76.       return;
  77.    }
  78.  
  79.    switch (type) {
  80.       case GL_2D:
  81.      ctx->Feedback.Mask = 0;
  82.          ctx->Feedback.Type = type;
  83.      break;
  84.       case GL_3D:
  85.      ctx->Feedback.Mask = FB_3D;
  86.          ctx->Feedback.Type = type;
  87.      break;
  88.       case GL_3D_COLOR:
  89.      ctx->Feedback.Mask = FB_3D
  90.                            | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX);
  91.          ctx->Feedback.Type = type;
  92.      break;
  93.       case GL_3D_COLOR_TEXTURE:
  94.      ctx->Feedback.Mask = FB_3D
  95.                            | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
  96.                        | FB_TEXTURE;
  97.          ctx->Feedback.Type = type;
  98.      break;
  99.       case GL_4D_COLOR_TEXTURE:
  100.      ctx->Feedback.Mask = FB_3D | FB_4D
  101.                            | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
  102.                        | FB_TEXTURE;
  103.          ctx->Feedback.Type = type;
  104.      break;
  105.       default:
  106.      ctx->Feedback.Mask = 0;
  107.          gl_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
  108.    }
  109.  
  110.    ctx->Feedback.BufferSize = size;
  111.    ctx->Feedback.Buffer = buffer;
  112.    ctx->Feedback.Count = 0;
  113. }
  114.  
  115.  
  116.  
  117. void gl_PassThrough( GLcontext *ctx, GLfloat token )
  118. {
  119.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPassThrough");
  120.  
  121.    if (ctx->RenderMode==GL_FEEDBACK) {
  122.       FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
  123.       FEEDBACK_TOKEN( ctx, token );
  124.    }
  125. }
  126.  
  127.  
  128.  
  129. /*
  130.  * Put a vertex into the feedback buffer.
  131.  */
  132. void gl_feedback_vertex( GLcontext *ctx,
  133.                          const GLfloat win[4],
  134.              const GLfloat color[4], 
  135.              GLuint index,
  136.              const GLfloat texcoord[4] )
  137. {
  138.    FEEDBACK_TOKEN( ctx, win[0] );
  139.    FEEDBACK_TOKEN( ctx, win[1] );
  140.    if (ctx->Feedback.Mask & FB_3D) {
  141.       FEEDBACK_TOKEN( ctx, win[2] );
  142.    }
  143.    if (ctx->Feedback.Mask & FB_4D) {
  144.       FEEDBACK_TOKEN( ctx, win[3] );
  145.    }
  146.    if (ctx->Feedback.Mask & FB_INDEX) {
  147.       FEEDBACK_TOKEN( ctx, (GLfloat) index );
  148.    }
  149.    if (ctx->Feedback.Mask & FB_COLOR) {
  150.       FEEDBACK_TOKEN( ctx, color[0] );
  151.       FEEDBACK_TOKEN( ctx, color[1] );
  152.       FEEDBACK_TOKEN( ctx, color[2] );
  153.       FEEDBACK_TOKEN( ctx, color[3] );
  154.    }
  155.    if (ctx->Feedback.Mask & FB_TEXTURE) {
  156.       FEEDBACK_TOKEN( ctx, texcoord[0] );
  157.       FEEDBACK_TOKEN( ctx, texcoord[1] );
  158.       FEEDBACK_TOKEN( ctx, texcoord[2] );
  159.       FEEDBACK_TOKEN( ctx, texcoord[3] );
  160.    }
  161. }
  162.  
  163.  
  164.  
  165. static void gl_do_feedback_vertex( GLcontext *ctx, GLuint v, GLuint pv )
  166. {
  167.    GLfloat win[4];
  168.    GLfloat color[4];
  169.    GLfloat tc[4];
  170.    GLuint texUnit = ctx->Texture.CurrentTransformUnit;
  171.    struct vertex_buffer *VB = ctx->VB;
  172.  
  173.    win[0] = VB->Win.data[v][0];
  174.    win[1] = VB->Win.data[v][1];
  175.    win[2] = VB->Win.data[v][2] / DEPTH_SCALE;
  176.    win[3] = 1.0 / VB->Win.data[v][3];
  177.  
  178.    if (ctx->Light.ShadeModel==GL_SMOOTH) pv = v;
  179.  
  180.    UBYTE_RGBA_TO_FLOAT_RGBA( color, VB->ColorPtr->data[pv] );
  181.  
  182.    if (VB->TexCoordPtr[texUnit]->size == 4 &&     
  183.        VB->TexCoordPtr[texUnit]->data[v][3]!=0.0)
  184.    {
  185.       GLfloat invq = 1.0F / VB->TexCoordPtr[texUnit]->data[v][3];
  186.       tc[0] = VB->TexCoordPtr[texUnit]->data[v][0] * invq;
  187.       tc[1] = VB->TexCoordPtr[texUnit]->data[v][1] * invq;
  188.       tc[2] = VB->TexCoordPtr[texUnit]->data[v][2] * invq;
  189.       tc[3] = VB->TexCoordPtr[texUnit]->data[v][3];
  190.    } else {
  191.       ASSIGN_4V(tc, 0,0,0,1);
  192.       COPY_SZ_4V(tc, 
  193.          VB->TexCoordPtr[texUnit]->size,
  194.          VB->TexCoordPtr[texUnit]->data[v]);
  195.    }
  196.  
  197.    gl_feedback_vertex( ctx, win, color, VB->IndexPtr->data[v], tc );
  198. }
  199.  
  200.  
  201.  
  202. /*
  203.  * Put triangle in feedback buffer.
  204.  */
  205. void gl_feedback_triangle( GLcontext *ctx,
  206.                GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  207. {
  208.    if (gl_cull_triangle( ctx, v0, v1, v2, 0 )) {
  209.       FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN );
  210.       FEEDBACK_TOKEN( ctx, (GLfloat) 3 );        /* three vertices */
  211.       
  212.       gl_do_feedback_vertex( ctx, v0, pv );
  213.       gl_do_feedback_vertex( ctx, v1, pv );
  214.       gl_do_feedback_vertex( ctx, v2, pv );
  215.    }
  216. }
  217.  
  218.  
  219. void gl_feedback_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  220. {
  221.    GLenum token = GL_LINE_TOKEN;
  222.  
  223.    if (ctx->StippleCounter==0) 
  224.       token = GL_LINE_RESET_TOKEN;
  225.  
  226.    FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) token );
  227.  
  228.    gl_do_feedback_vertex( ctx, v1, pv );
  229.    gl_do_feedback_vertex( ctx, v2, pv );
  230.  
  231.    ctx->StippleCounter++;
  232. }
  233.  
  234.  
  235. void gl_feedback_points( GLcontext *ctx, GLuint first, GLuint last )
  236. {
  237.    struct vertex_buffer *VB = ctx->VB;
  238.    GLuint i;
  239.  
  240.    for (i=first;i<=last;i++) 
  241.       if (VB->ClipMask[i]==0) {
  242.          FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POINT_TOKEN );
  243.      gl_do_feedback_vertex( ctx, i, i );
  244.       }
  245. }
  246.  
  247.  
  248.  
  249.  
  250.  
  251. /**********************************************************************/
  252. /*                              Selection                             */
  253. /**********************************************************************/
  254.  
  255.  
  256. /*
  257.  * NOTE: this function can't be put in a display list.
  258.  */
  259. void gl_SelectBuffer( GLcontext *ctx, GLsizei size, GLuint *buffer )
  260. {
  261.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glSelectBuffer");
  262.    if (ctx->RenderMode==GL_SELECT) {
  263.       gl_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
  264.    }
  265.    ctx->Select.Buffer = buffer;
  266.    ctx->Select.BufferSize = size;
  267.    ctx->Select.BufferCount = 0;
  268.  
  269.    ctx->Select.HitFlag = GL_FALSE;
  270.    ctx->Select.HitMinZ = 1.0;
  271.    ctx->Select.HitMaxZ = 0.0;
  272. }
  273.  
  274.  
  275. #define WRITE_RECORD( CTX, V )                    \
  276.     if (CTX->Select.BufferCount < CTX->Select.BufferSize) {    \
  277.        CTX->Select.Buffer[CTX->Select.BufferCount] = (V);    \
  278.     }                            \
  279.     CTX->Select.BufferCount++;
  280.  
  281.  
  282.  
  283. void gl_update_hitflag( GLcontext *ctx, GLfloat z )
  284. {
  285.    ctx->Select.HitFlag = GL_TRUE;
  286.    if (z < ctx->Select.HitMinZ) {
  287.       ctx->Select.HitMinZ = z;
  288.    }
  289.    if (z > ctx->Select.HitMaxZ) {
  290.       ctx->Select.HitMaxZ = z;
  291.    }
  292. }
  293.  
  294. void gl_select_triangle( GLcontext *ctx,
  295.              GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  296. {
  297.    struct vertex_buffer *VB = ctx->VB;
  298.  
  299.    if (gl_cull_triangle( ctx, v0, v1, v2, 0 )) {
  300.       gl_update_hitflag( ctx, VB->Win.data[v0][3] / DEPTH_SCALE );
  301.       gl_update_hitflag( ctx, VB->Win.data[v1][3] / DEPTH_SCALE );
  302.       gl_update_hitflag( ctx, VB->Win.data[v2][3] / DEPTH_SCALE );
  303.    }
  304. }
  305.  
  306.  
  307. void gl_select_line( GLcontext *ctx,
  308.              GLuint v0, GLuint v1, GLuint pv )
  309. {
  310.    struct vertex_buffer *VB = ctx->VB;
  311.  
  312.    gl_update_hitflag( ctx, VB->Win.data[v0][3] / DEPTH_SCALE );
  313.    gl_update_hitflag( ctx, VB->Win.data[v1][3] / DEPTH_SCALE );
  314. }
  315.  
  316. void gl_select_points( GLcontext *ctx, GLuint first, GLuint last )
  317. {
  318.    struct vertex_buffer *VB = ctx->VB;
  319.    GLuint i;
  320.  
  321.    for (i=first;i<=last;i++) 
  322.       if (VB->ClipMask[i]==0) 
  323.          gl_update_hitflag( ctx, VB->Win.data[i][3] / DEPTH_SCALE);
  324. }
  325.  
  326.  
  327. static void write_hit_record( GLcontext *ctx )
  328. {
  329.    GLuint i;
  330.    GLuint zmin, zmax, zscale = (~0u);
  331.  
  332.    /* HitMinZ and HitMaxZ are in [0,1].  Multiply these values by */
  333.    /* 2^32-1 and round to nearest unsigned integer. */
  334.  
  335.    assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */
  336.    zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
  337.    zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
  338.  
  339.    WRITE_RECORD( ctx, ctx->Select.NameStackDepth );
  340.    WRITE_RECORD( ctx, zmin );
  341.    WRITE_RECORD( ctx, zmax );
  342.    for (i=0;i<ctx->Select.NameStackDepth;i++) {
  343.       WRITE_RECORD( ctx, ctx->Select.NameStack[i] );
  344.    }
  345.  
  346.    ctx->Select.Hits++;
  347.    ctx->Select.HitFlag = GL_FALSE;
  348.    ctx->Select.HitMinZ = 1.0;
  349.    ctx->Select.HitMaxZ = -1.0;
  350. }
  351.  
  352.  
  353.  
  354. void gl_InitNames( GLcontext *ctx )
  355. {
  356.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glInitNames");
  357.    /* Record the hit before the HitFlag is wiped out again. */
  358.    if (ctx->RenderMode==GL_SELECT) {
  359.       if (ctx->Select.HitFlag) {
  360.          write_hit_record( ctx );
  361.       }
  362.    }
  363.    ctx->Select.NameStackDepth = 0;
  364.    ctx->Select.HitFlag = GL_FALSE;
  365.    ctx->Select.HitMinZ = 1.0;
  366.    ctx->Select.HitMaxZ = 0.0;
  367. }
  368.  
  369.  
  370.  
  371. void gl_LoadName( GLcontext *ctx, GLuint name )
  372. {
  373.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLoadName");
  374.    if (ctx->RenderMode!=GL_SELECT) {
  375.       return;
  376.    }
  377.    if (ctx->Select.NameStackDepth==0) {
  378.       gl_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
  379.       return;
  380.    }
  381.    if (ctx->Select.HitFlag) {
  382.       write_hit_record( ctx );
  383.    }
  384.    if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) {
  385.       ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name;
  386.    }
  387.    else {
  388.       ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name;
  389.    }
  390. }
  391.  
  392.  
  393. void gl_PushName( GLcontext *ctx, GLuint name )
  394. {
  395.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushName");
  396.    if (ctx->RenderMode!=GL_SELECT) {
  397.       return;
  398.    }
  399.    if (ctx->Select.HitFlag) {
  400.       write_hit_record( ctx );
  401.    }
  402.    if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) {
  403.       ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
  404.    }
  405.    else {
  406.       gl_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
  407.    }
  408. }
  409.  
  410.  
  411.  
  412. void gl_PopName( GLcontext *ctx )
  413. {
  414.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopName");
  415.    if (ctx->RenderMode!=GL_SELECT) {
  416.       return;
  417.    }
  418.    if (ctx->Select.HitFlag) {
  419.       write_hit_record( ctx );
  420.    }
  421.    if (ctx->Select.NameStackDepth>0) {
  422.       ctx->Select.NameStackDepth--;
  423.    }
  424.    else {
  425.       gl_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
  426.    }
  427. }
  428.  
  429.  
  430.  
  431. /**********************************************************************/
  432. /*                           Render Mode                              */
  433. /**********************************************************************/
  434.  
  435.  
  436.  
  437. /*
  438.  * NOTE: this function can't be put in a display list.
  439.  */
  440. GLint gl_RenderMode( GLcontext *ctx, GLenum mode )
  441. {
  442.    GLint result;
  443.  
  444.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glRenderMode", 0);
  445.  
  446.    if (MESA_VERBOSE & VERBOSE_API)
  447.       fprintf(stderr, "glRenderMode %s\n", gl_lookup_enum_by_nr(mode));
  448.  
  449.    ctx->TriangleCaps &= ~(DD_FEEDBACK|DD_SELECT);
  450.  
  451.    switch (ctx->RenderMode) {
  452.       case GL_RENDER:
  453.      result = 0;
  454.      break;
  455.       case GL_SELECT:
  456.      if (ctx->Select.HitFlag) {
  457.         write_hit_record( ctx );
  458.      }
  459.      if (ctx->Select.BufferCount > ctx->Select.BufferSize) {
  460.         /* overflow */
  461. #ifdef DEBUG
  462.             gl_warning(ctx, "Feedback buffer overflow");
  463. #endif
  464.         result = -1;
  465.      }
  466.      else {
  467.         result = ctx->Select.Hits;
  468.      }
  469.      ctx->Select.BufferCount = 0;
  470.      ctx->Select.Hits = 0;
  471.      ctx->Select.NameStackDepth = 0;
  472.      break;
  473.       case GL_FEEDBACK:
  474.      if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
  475.         /* overflow */
  476.         result = -1;
  477.      }
  478.      else {
  479.         result = ctx->Feedback.Count;
  480.      }
  481.      ctx->Feedback.Count = 0;
  482.      break;
  483.       default:
  484.      gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
  485.      return 0;
  486.    }
  487.  
  488.    switch (mode) {
  489.       case GL_RENDER:
  490.          break;
  491.       case GL_SELECT:
  492.      ctx->TriangleCaps |= DD_SELECT;
  493.      if (ctx->Select.BufferSize==0) {
  494.         /* haven't called glSelectBuffer yet */
  495.         gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  496.      }
  497.      break;
  498.       case GL_FEEDBACK:
  499.      ctx->TriangleCaps |= DD_FEEDBACK;
  500.      if (ctx->Feedback.BufferSize==0) {
  501.         /* haven't called glFeedbackBuffer yet */
  502.         gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  503.      }
  504.      break;
  505.       default:
  506.      gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
  507.      return 0;
  508.    }
  509.  
  510.  
  511.    ctx->RenderMode = mode;
  512.    ctx->NewState |= NEW_ALL;
  513.  
  514.    return result;
  515. }
  516.  
  517.