feedback.c revision cdc920a0
17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
34a49301eSmrg * Version:  7.5
47117f1b4Smrg *
54a49301eSmrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
64a49301eSmrg * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
77117f1b4Smrg *
87117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
97117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
107117f1b4Smrg * to deal in the Software without restriction, including without limitation
117117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
127117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
137117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
147117f1b4Smrg *
157117f1b4Smrg * The above copyright notice and this permission notice shall be included
167117f1b4Smrg * in all copies or substantial portions of the Software.
177117f1b4Smrg *
187117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
197117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
207117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
217117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
227117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
237117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
247117f1b4Smrg */
257117f1b4Smrg
264a49301eSmrg/**
274a49301eSmrg * \file feedback.c
284a49301eSmrg * Selection and feedback modes functions.
294a49301eSmrg */
304a49301eSmrg
317117f1b4Smrg
327117f1b4Smrg#include "glheader.h"
337117f1b4Smrg#include "colormac.h"
347117f1b4Smrg#include "context.h"
357117f1b4Smrg#include "enums.h"
367117f1b4Smrg#include "feedback.h"
377117f1b4Smrg#include "macros.h"
387117f1b4Smrg#include "mtypes.h"
39cdc920a0Smrg#include "main/dispatch.h"
407117f1b4Smrg
417117f1b4Smrg
424a49301eSmrg#if FEATURE_feedback
437117f1b4Smrg
447117f1b4Smrg
457117f1b4Smrg#define FB_3D		0x01
467117f1b4Smrg#define FB_4D		0x02
47cdc920a0Smrg#define FB_COLOR	0x04
48cdc920a0Smrg#define FB_TEXTURE	0X08
497117f1b4Smrg
507117f1b4Smrg
517117f1b4Smrg
524a49301eSmrgstatic void GLAPIENTRY
537117f1b4Smrg_mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer )
547117f1b4Smrg{
557117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
567117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
577117f1b4Smrg
587117f1b4Smrg   if (ctx->RenderMode==GL_FEEDBACK) {
597117f1b4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
607117f1b4Smrg      return;
617117f1b4Smrg   }
627117f1b4Smrg   if (size<0) {
637117f1b4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
647117f1b4Smrg      return;
657117f1b4Smrg   }
667117f1b4Smrg   if (!buffer) {
677117f1b4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
687117f1b4Smrg      ctx->Feedback.BufferSize = 0;
697117f1b4Smrg      return;
707117f1b4Smrg   }
717117f1b4Smrg
727117f1b4Smrg   switch (type) {
737117f1b4Smrg      case GL_2D:
747117f1b4Smrg	 ctx->Feedback._Mask = 0;
757117f1b4Smrg	 break;
767117f1b4Smrg      case GL_3D:
777117f1b4Smrg	 ctx->Feedback._Mask = FB_3D;
787117f1b4Smrg	 break;
797117f1b4Smrg      case GL_3D_COLOR:
80cdc920a0Smrg	 ctx->Feedback._Mask = (FB_3D | FB_COLOR);
817117f1b4Smrg	 break;
827117f1b4Smrg      case GL_3D_COLOR_TEXTURE:
83cdc920a0Smrg	 ctx->Feedback._Mask = (FB_3D | FB_COLOR | FB_TEXTURE);
847117f1b4Smrg	 break;
857117f1b4Smrg      case GL_4D_COLOR_TEXTURE:
86cdc920a0Smrg	 ctx->Feedback._Mask = (FB_3D | FB_4D | FB_COLOR | FB_TEXTURE);
877117f1b4Smrg	 break;
887117f1b4Smrg      default:
897117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
907117f1b4Smrg	 return;
917117f1b4Smrg   }
927117f1b4Smrg
937117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE); /* Always flush */
947117f1b4Smrg   ctx->Feedback.Type = type;
957117f1b4Smrg   ctx->Feedback.BufferSize = size;
967117f1b4Smrg   ctx->Feedback.Buffer = buffer;
977117f1b4Smrg   ctx->Feedback.Count = 0;	              /* Becaues of this. */
987117f1b4Smrg}
997117f1b4Smrg
1007117f1b4Smrg
1014a49301eSmrgstatic void GLAPIENTRY
1027117f1b4Smrg_mesa_PassThrough( GLfloat token )
1037117f1b4Smrg{
1047117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1057117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1067117f1b4Smrg
1077117f1b4Smrg   if (ctx->RenderMode==GL_FEEDBACK) {
1087117f1b4Smrg      FLUSH_VERTICES(ctx, 0);
1094a49301eSmrg      _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
1104a49301eSmrg      _mesa_feedback_token( ctx, token );
1117117f1b4Smrg   }
1127117f1b4Smrg}
1137117f1b4Smrg
1147117f1b4Smrg
1154a49301eSmrg/**
1167117f1b4Smrg * Put a vertex into the feedback buffer.
1177117f1b4Smrg */
1184a49301eSmrgvoid
1194a49301eSmrg_mesa_feedback_vertex(GLcontext *ctx,
1204a49301eSmrg                      const GLfloat win[4],
1214a49301eSmrg                      const GLfloat color[4],
1224a49301eSmrg                      const GLfloat texcoord[4])
1237117f1b4Smrg{
1244a49301eSmrg   _mesa_feedback_token( ctx, win[0] );
1254a49301eSmrg   _mesa_feedback_token( ctx, win[1] );
1267117f1b4Smrg   if (ctx->Feedback._Mask & FB_3D) {
1274a49301eSmrg      _mesa_feedback_token( ctx, win[2] );
1287117f1b4Smrg   }
1297117f1b4Smrg   if (ctx->Feedback._Mask & FB_4D) {
1304a49301eSmrg      _mesa_feedback_token( ctx, win[3] );
1317117f1b4Smrg   }
1327117f1b4Smrg   if (ctx->Feedback._Mask & FB_COLOR) {
1334a49301eSmrg      _mesa_feedback_token( ctx, color[0] );
1344a49301eSmrg      _mesa_feedback_token( ctx, color[1] );
1354a49301eSmrg      _mesa_feedback_token( ctx, color[2] );
1364a49301eSmrg      _mesa_feedback_token( ctx, color[3] );
1377117f1b4Smrg   }
1387117f1b4Smrg   if (ctx->Feedback._Mask & FB_TEXTURE) {
1394a49301eSmrg      _mesa_feedback_token( ctx, texcoord[0] );
1404a49301eSmrg      _mesa_feedback_token( ctx, texcoord[1] );
1414a49301eSmrg      _mesa_feedback_token( ctx, texcoord[2] );
1424a49301eSmrg      _mesa_feedback_token( ctx, texcoord[3] );
1437117f1b4Smrg   }
1447117f1b4Smrg}
1457117f1b4Smrg
1467117f1b4Smrg
1477117f1b4Smrg/**********************************************************************/
1487117f1b4Smrg/** \name Selection */
1497117f1b4Smrg/*@{*/
1507117f1b4Smrg
1517117f1b4Smrg/**
1527117f1b4Smrg * Establish a buffer for selection mode values.
1537117f1b4Smrg *
1547117f1b4Smrg * \param size buffer size.
1557117f1b4Smrg * \param buffer buffer.
1567117f1b4Smrg *
1577117f1b4Smrg * \sa glSelectBuffer().
1587117f1b4Smrg *
1597117f1b4Smrg * \note this function can't be put in a display list.
1607117f1b4Smrg *
1617117f1b4Smrg * Verifies we're not in selection mode, flushes the vertices and initialize
1627117f1b4Smrg * the fields in __GLcontextRec::Select with the given buffer.
1637117f1b4Smrg */
1644a49301eSmrgstatic void GLAPIENTRY
1657117f1b4Smrg_mesa_SelectBuffer( GLsizei size, GLuint *buffer )
1667117f1b4Smrg{
1677117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1687117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1697117f1b4Smrg
1707117f1b4Smrg   if (ctx->RenderMode==GL_SELECT) {
1717117f1b4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
1727117f1b4Smrg      return;			/* KW: added return */
1737117f1b4Smrg   }
1747117f1b4Smrg
1757117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
1767117f1b4Smrg   ctx->Select.Buffer = buffer;
1777117f1b4Smrg   ctx->Select.BufferSize = size;
1787117f1b4Smrg   ctx->Select.BufferCount = 0;
1797117f1b4Smrg   ctx->Select.HitFlag = GL_FALSE;
1807117f1b4Smrg   ctx->Select.HitMinZ = 1.0;
1817117f1b4Smrg   ctx->Select.HitMaxZ = 0.0;
1827117f1b4Smrg}
1837117f1b4Smrg
1847117f1b4Smrg
1857117f1b4Smrg/**
1867117f1b4Smrg * Write a value of a record into the selection buffer.
1877117f1b4Smrg *
1884a49301eSmrg * \param ctx GL context.
1894a49301eSmrg * \param value value.
1907117f1b4Smrg *
1917117f1b4Smrg * Verifies there is free space in the buffer to write the value and
1927117f1b4Smrg * increments the pointer.
1937117f1b4Smrg */
1944a49301eSmrgstatic INLINE void
1954a49301eSmrgwrite_record(GLcontext *ctx, GLuint value)
1964a49301eSmrg{
1974a49301eSmrg   if (ctx->Select.BufferCount < ctx->Select.BufferSize) {
1984a49301eSmrg      ctx->Select.Buffer[ctx->Select.BufferCount] = value;
1994a49301eSmrg   }
2004a49301eSmrg   ctx->Select.BufferCount++;
2014a49301eSmrg}
2027117f1b4Smrg
2037117f1b4Smrg
2047117f1b4Smrg/**
2057117f1b4Smrg * Update the hit flag and the maximum and minimum depth values.
2067117f1b4Smrg *
2077117f1b4Smrg * \param ctx GL context.
2087117f1b4Smrg * \param z depth.
2097117f1b4Smrg *
2107117f1b4Smrg * Sets gl_selection::HitFlag and updates gl_selection::HitMinZ and
2117117f1b4Smrg * gl_selection::HitMaxZ.
2127117f1b4Smrg */
2134a49301eSmrgvoid
2144a49301eSmrg_mesa_update_hitflag(GLcontext *ctx, GLfloat z)
2157117f1b4Smrg{
2167117f1b4Smrg   ctx->Select.HitFlag = GL_TRUE;
2177117f1b4Smrg   if (z < ctx->Select.HitMinZ) {
2187117f1b4Smrg      ctx->Select.HitMinZ = z;
2197117f1b4Smrg   }
2207117f1b4Smrg   if (z > ctx->Select.HitMaxZ) {
2217117f1b4Smrg      ctx->Select.HitMaxZ = z;
2227117f1b4Smrg   }
2237117f1b4Smrg}
2247117f1b4Smrg
2257117f1b4Smrg
2267117f1b4Smrg/**
2277117f1b4Smrg * Write the hit record.
2287117f1b4Smrg *
2297117f1b4Smrg * \param ctx GL context.
2307117f1b4Smrg *
2317117f1b4Smrg * Write the hit record, i.e., the number of names in the stack, the minimum and
2327117f1b4Smrg * maximum depth values and the number of names in the name stack at the time
2337117f1b4Smrg * of the event. Resets the hit flag.
2347117f1b4Smrg *
2357117f1b4Smrg * \sa gl_selection.
2367117f1b4Smrg */
2374a49301eSmrgstatic void
2384a49301eSmrgwrite_hit_record(GLcontext *ctx)
2397117f1b4Smrg{
2407117f1b4Smrg   GLuint i;
2417117f1b4Smrg   GLuint zmin, zmax, zscale = (~0u);
2427117f1b4Smrg
2437117f1b4Smrg   /* HitMinZ and HitMaxZ are in [0,1].  Multiply these values by */
2447117f1b4Smrg   /* 2^32-1 and round to nearest unsigned integer. */
2457117f1b4Smrg
2467117f1b4Smrg   assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */
2477117f1b4Smrg   zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
2487117f1b4Smrg   zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
2497117f1b4Smrg
2504a49301eSmrg   write_record( ctx, ctx->Select.NameStackDepth );
2514a49301eSmrg   write_record( ctx, zmin );
2524a49301eSmrg   write_record( ctx, zmax );
2537117f1b4Smrg   for (i = 0; i < ctx->Select.NameStackDepth; i++) {
2544a49301eSmrg      write_record( ctx, ctx->Select.NameStack[i] );
2557117f1b4Smrg   }
2567117f1b4Smrg
2577117f1b4Smrg   ctx->Select.Hits++;
2587117f1b4Smrg   ctx->Select.HitFlag = GL_FALSE;
2597117f1b4Smrg   ctx->Select.HitMinZ = 1.0;
2607117f1b4Smrg   ctx->Select.HitMaxZ = -1.0;
2617117f1b4Smrg}
2627117f1b4Smrg
2637117f1b4Smrg
2647117f1b4Smrg/**
2657117f1b4Smrg * Initialize the name stack.
2667117f1b4Smrg *
2677117f1b4Smrg * Verifies we are in select mode and resets the name stack depth and resets
2687117f1b4Smrg * the hit record data in gl_selection. Marks new render mode in
2697117f1b4Smrg * __GLcontextRec::NewState.
2707117f1b4Smrg */
2714a49301eSmrgstatic void GLAPIENTRY
2727117f1b4Smrg_mesa_InitNames( void )
2737117f1b4Smrg{
2747117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2757117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2767117f1b4Smrg
2777117f1b4Smrg   /* Record the hit before the HitFlag is wiped out again. */
2787117f1b4Smrg   if (ctx->RenderMode == GL_SELECT) {
2797117f1b4Smrg      if (ctx->Select.HitFlag) {
2807117f1b4Smrg         write_hit_record( ctx );
2817117f1b4Smrg      }
2827117f1b4Smrg   }
2837117f1b4Smrg   ctx->Select.NameStackDepth = 0;
2847117f1b4Smrg   ctx->Select.HitFlag = GL_FALSE;
2857117f1b4Smrg   ctx->Select.HitMinZ = 1.0;
2867117f1b4Smrg   ctx->Select.HitMaxZ = 0.0;
2877117f1b4Smrg   ctx->NewState |= _NEW_RENDERMODE;
2887117f1b4Smrg}
2897117f1b4Smrg
2907117f1b4Smrg
2917117f1b4Smrg/**
2927117f1b4Smrg * Load the top-most name of the name stack.
2937117f1b4Smrg *
2947117f1b4Smrg * \param name name.
2957117f1b4Smrg *
2967117f1b4Smrg * Verifies we are in selection mode and that the name stack is not empty.
2977117f1b4Smrg * Flushes vertices. If there is a hit flag writes it (via write_hit_record()),
2987117f1b4Smrg * and replace the top-most name in the stack.
2997117f1b4Smrg *
3007117f1b4Smrg * sa __GLcontextRec::Select.
3017117f1b4Smrg */
3024a49301eSmrgstatic void GLAPIENTRY
3037117f1b4Smrg_mesa_LoadName( GLuint name )
3047117f1b4Smrg{
3057117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
3067117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
3077117f1b4Smrg
3087117f1b4Smrg   if (ctx->RenderMode != GL_SELECT) {
3097117f1b4Smrg      return;
3107117f1b4Smrg   }
3117117f1b4Smrg   if (ctx->Select.NameStackDepth == 0) {
3127117f1b4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
3137117f1b4Smrg      return;
3147117f1b4Smrg   }
3157117f1b4Smrg
3167117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
3177117f1b4Smrg
3187117f1b4Smrg   if (ctx->Select.HitFlag) {
3197117f1b4Smrg      write_hit_record( ctx );
3207117f1b4Smrg   }
3217117f1b4Smrg   if (ctx->Select.NameStackDepth < MAX_NAME_STACK_DEPTH) {
3227117f1b4Smrg      ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name;
3237117f1b4Smrg   }
3247117f1b4Smrg   else {
3257117f1b4Smrg      ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name;
3267117f1b4Smrg   }
3277117f1b4Smrg}
3287117f1b4Smrg
3297117f1b4Smrg
3307117f1b4Smrg/**
3317117f1b4Smrg * Push a name into the name stack.
3327117f1b4Smrg *
3337117f1b4Smrg * \param name name.
3347117f1b4Smrg *
3357117f1b4Smrg * Verifies we are in selection mode and that the name stack is not full.
3367117f1b4Smrg * Flushes vertices. If there is a hit flag writes it (via write_hit_record()),
3377117f1b4Smrg * and adds the name to the top of the name stack.
3387117f1b4Smrg *
3397117f1b4Smrg * sa __GLcontextRec::Select.
3407117f1b4Smrg */
3414a49301eSmrgstatic void GLAPIENTRY
3427117f1b4Smrg_mesa_PushName( GLuint name )
3437117f1b4Smrg{
3447117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
3457117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
3467117f1b4Smrg
3477117f1b4Smrg   if (ctx->RenderMode != GL_SELECT) {
3487117f1b4Smrg      return;
3497117f1b4Smrg   }
3507117f1b4Smrg
3517117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
3527117f1b4Smrg   if (ctx->Select.HitFlag) {
3537117f1b4Smrg      write_hit_record( ctx );
3547117f1b4Smrg   }
3557117f1b4Smrg   if (ctx->Select.NameStackDepth >= MAX_NAME_STACK_DEPTH) {
3567117f1b4Smrg      _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
3577117f1b4Smrg   }
3587117f1b4Smrg   else
3597117f1b4Smrg      ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
3607117f1b4Smrg}
3617117f1b4Smrg
3627117f1b4Smrg
3637117f1b4Smrg/**
3647117f1b4Smrg * Pop a name into the name stack.
3657117f1b4Smrg *
3667117f1b4Smrg * Verifies we are in selection mode and that the name stack is not empty.
3677117f1b4Smrg * Flushes vertices. If there is a hit flag writes it (via write_hit_record()),
3687117f1b4Smrg * and removes top-most name in the name stack.
3697117f1b4Smrg *
3707117f1b4Smrg * sa __GLcontextRec::Select.
3717117f1b4Smrg */
3724a49301eSmrgstatic void GLAPIENTRY
3737117f1b4Smrg_mesa_PopName( void )
3747117f1b4Smrg{
3757117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
3767117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
3777117f1b4Smrg
3787117f1b4Smrg   if (ctx->RenderMode != GL_SELECT) {
3797117f1b4Smrg      return;
3807117f1b4Smrg   }
3817117f1b4Smrg
3827117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
3837117f1b4Smrg   if (ctx->Select.HitFlag) {
3847117f1b4Smrg      write_hit_record( ctx );
3857117f1b4Smrg   }
3867117f1b4Smrg   if (ctx->Select.NameStackDepth == 0) {
3877117f1b4Smrg      _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
3887117f1b4Smrg   }
3897117f1b4Smrg   else
3907117f1b4Smrg      ctx->Select.NameStackDepth--;
3917117f1b4Smrg}
3927117f1b4Smrg
3937117f1b4Smrg/*@}*/
3947117f1b4Smrg
3957117f1b4Smrg
3967117f1b4Smrg/**********************************************************************/
3977117f1b4Smrg/** \name Render Mode */
3987117f1b4Smrg/*@{*/
3997117f1b4Smrg
4007117f1b4Smrg/**
4017117f1b4Smrg * Set rasterization mode.
4027117f1b4Smrg *
4037117f1b4Smrg * \param mode rasterization mode.
4047117f1b4Smrg *
4057117f1b4Smrg * \note this function can't be put in a display list.
4067117f1b4Smrg *
4077117f1b4Smrg * \sa glRenderMode().
4087117f1b4Smrg *
4097117f1b4Smrg * Flushes the vertices and do the necessary cleanup according to the previous
4107117f1b4Smrg * rasterization mode, such as writing the hit record or resent the select
4117117f1b4Smrg * buffer index when exiting the select mode. Updates
4127117f1b4Smrg * __GLcontextRec::RenderMode and notifies the driver via the
4137117f1b4Smrg * dd_function_table::RenderMode callback.
4147117f1b4Smrg */
4154a49301eSmrgstatic GLint GLAPIENTRY
4167117f1b4Smrg_mesa_RenderMode( GLenum mode )
4177117f1b4Smrg{
4187117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
4197117f1b4Smrg   GLint result;
4207117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
4217117f1b4Smrg
4227117f1b4Smrg   if (MESA_VERBOSE & VERBOSE_API)
4237117f1b4Smrg      _mesa_debug(ctx, "glRenderMode %s\n", _mesa_lookup_enum_by_nr(mode));
4247117f1b4Smrg
4257117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
4267117f1b4Smrg
4277117f1b4Smrg   switch (ctx->RenderMode) {
4287117f1b4Smrg      case GL_RENDER:
4297117f1b4Smrg	 result = 0;
4307117f1b4Smrg	 break;
4317117f1b4Smrg      case GL_SELECT:
4327117f1b4Smrg	 if (ctx->Select.HitFlag) {
4337117f1b4Smrg	    write_hit_record( ctx );
4347117f1b4Smrg	 }
4357117f1b4Smrg	 if (ctx->Select.BufferCount > ctx->Select.BufferSize) {
4367117f1b4Smrg	    /* overflow */
4377117f1b4Smrg#ifdef DEBUG
4387117f1b4Smrg            _mesa_warning(ctx, "Feedback buffer overflow");
4397117f1b4Smrg#endif
4407117f1b4Smrg	    result = -1;
4417117f1b4Smrg	 }
4427117f1b4Smrg	 else {
4437117f1b4Smrg	    result = ctx->Select.Hits;
4447117f1b4Smrg	 }
4457117f1b4Smrg	 ctx->Select.BufferCount = 0;
4467117f1b4Smrg	 ctx->Select.Hits = 0;
4477117f1b4Smrg	 ctx->Select.NameStackDepth = 0;
4487117f1b4Smrg	 break;
4497117f1b4Smrg#if _HAVE_FULL_GL
4507117f1b4Smrg      case GL_FEEDBACK:
4517117f1b4Smrg	 if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
4527117f1b4Smrg	    /* overflow */
4537117f1b4Smrg	    result = -1;
4547117f1b4Smrg	 }
4557117f1b4Smrg	 else {
4567117f1b4Smrg	    result = ctx->Feedback.Count;
4577117f1b4Smrg	 }
4587117f1b4Smrg	 ctx->Feedback.Count = 0;
4597117f1b4Smrg	 break;
4607117f1b4Smrg#endif
4617117f1b4Smrg      default:
4627117f1b4Smrg	 _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
4637117f1b4Smrg	 return 0;
4647117f1b4Smrg   }
4657117f1b4Smrg
4667117f1b4Smrg   switch (mode) {
4677117f1b4Smrg      case GL_RENDER:
4687117f1b4Smrg         break;
4697117f1b4Smrg      case GL_SELECT:
4707117f1b4Smrg	 if (ctx->Select.BufferSize==0) {
4717117f1b4Smrg	    /* haven't called glSelectBuffer yet */
4727117f1b4Smrg	    _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
4737117f1b4Smrg	 }
4747117f1b4Smrg	 break;
4757117f1b4Smrg#if _HAVE_FULL_GL
4767117f1b4Smrg      case GL_FEEDBACK:
4777117f1b4Smrg	 if (ctx->Feedback.BufferSize==0) {
4787117f1b4Smrg	    /* haven't called glFeedbackBuffer yet */
4797117f1b4Smrg	    _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
4807117f1b4Smrg	 }
4817117f1b4Smrg	 break;
4827117f1b4Smrg#endif
4837117f1b4Smrg      default:
4847117f1b4Smrg	 _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
4857117f1b4Smrg	 return 0;
4867117f1b4Smrg   }
4877117f1b4Smrg
4887117f1b4Smrg   ctx->RenderMode = mode;
4897117f1b4Smrg   if (ctx->Driver.RenderMode)
4907117f1b4Smrg      ctx->Driver.RenderMode( ctx, mode );
4917117f1b4Smrg
4927117f1b4Smrg   return result;
4937117f1b4Smrg}
4947117f1b4Smrg
4957117f1b4Smrg/*@}*/
4967117f1b4Smrg
4977117f1b4Smrg
4984a49301eSmrgvoid
4994a49301eSmrg_mesa_init_feedback_dispatch(struct _glapi_table *disp)
5004a49301eSmrg{
5014a49301eSmrg   SET_InitNames(disp, _mesa_InitNames);
5024a49301eSmrg   SET_FeedbackBuffer(disp, _mesa_FeedbackBuffer);
5034a49301eSmrg   SET_LoadName(disp, _mesa_LoadName);
5044a49301eSmrg   SET_PassThrough(disp, _mesa_PassThrough);
5054a49301eSmrg   SET_PopName(disp, _mesa_PopName);
5064a49301eSmrg   SET_PushName(disp, _mesa_PushName);
5074a49301eSmrg   SET_SelectBuffer(disp, _mesa_SelectBuffer);
5084a49301eSmrg   SET_RenderMode(disp, _mesa_RenderMode);
5094a49301eSmrg}
5104a49301eSmrg
5114a49301eSmrg
5124a49301eSmrg#endif /* FEATURE_feedback */
5134a49301eSmrg
5144a49301eSmrg
5157117f1b4Smrg/**********************************************************************/
5167117f1b4Smrg/** \name Initialization */
5177117f1b4Smrg/*@{*/
5187117f1b4Smrg
5197117f1b4Smrg/**
5207117f1b4Smrg * Initialize context feedback data.
5217117f1b4Smrg */
5227117f1b4Smrgvoid _mesa_init_feedback( GLcontext * ctx )
5237117f1b4Smrg{
5247117f1b4Smrg   /* Feedback */
5257117f1b4Smrg   ctx->Feedback.Type = GL_2D;   /* TODO: verify */
5267117f1b4Smrg   ctx->Feedback.Buffer = NULL;
5277117f1b4Smrg   ctx->Feedback.BufferSize = 0;
5287117f1b4Smrg   ctx->Feedback.Count = 0;
5297117f1b4Smrg
5307117f1b4Smrg   /* Selection/picking */
5317117f1b4Smrg   ctx->Select.Buffer = NULL;
5327117f1b4Smrg   ctx->Select.BufferSize = 0;
5337117f1b4Smrg   ctx->Select.BufferCount = 0;
5347117f1b4Smrg   ctx->Select.Hits = 0;
5357117f1b4Smrg   ctx->Select.NameStackDepth = 0;
5367117f1b4Smrg
5377117f1b4Smrg   /* Miscellaneous */
5387117f1b4Smrg   ctx->RenderMode = GL_RENDER;
5397117f1b4Smrg}
5407117f1b4Smrg
5417117f1b4Smrg/*@}*/
542