17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
37117f1b4Smrg *
44a49301eSmrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
54a49301eSmrg * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
67117f1b4Smrg *
77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
87117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
97117f1b4Smrg * to deal in the Software without restriction, including without limitation
107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
127117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
137117f1b4Smrg *
147117f1b4Smrg * The above copyright notice and this permission notice shall be included
157117f1b4Smrg * in all copies or substantial portions of the Software.
167117f1b4Smrg *
177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23af69d88dSmrg * 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 "context.h"
347117f1b4Smrg#include "enums.h"
357117f1b4Smrg#include "feedback.h"
367117f1b4Smrg#include "macros.h"
377117f1b4Smrg#include "mtypes.h"
387117f1b4Smrg
397117f1b4Smrg
407117f1b4Smrg#define FB_3D		0x01
417117f1b4Smrg#define FB_4D		0x02
42cdc920a0Smrg#define FB_COLOR	0x04
43cdc920a0Smrg#define FB_TEXTURE	0X08
447117f1b4Smrg
457117f1b4Smrg
467117f1b4Smrg
47af69d88dSmrgvoid GLAPIENTRY
487117f1b4Smrg_mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer )
497117f1b4Smrg{
507117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
517117f1b4Smrg
527117f1b4Smrg   if (ctx->RenderMode==GL_FEEDBACK) {
537117f1b4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
547117f1b4Smrg      return;
557117f1b4Smrg   }
567117f1b4Smrg   if (size<0) {
577117f1b4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
587117f1b4Smrg      return;
597117f1b4Smrg   }
603464ebd5Sriastradh   if (!buffer && size > 0) {
617117f1b4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
627117f1b4Smrg      ctx->Feedback.BufferSize = 0;
637117f1b4Smrg      return;
647117f1b4Smrg   }
657117f1b4Smrg
667117f1b4Smrg   switch (type) {
677117f1b4Smrg      case GL_2D:
687117f1b4Smrg	 ctx->Feedback._Mask = 0;
697117f1b4Smrg	 break;
707117f1b4Smrg      case GL_3D:
717117f1b4Smrg	 ctx->Feedback._Mask = FB_3D;
727117f1b4Smrg	 break;
737117f1b4Smrg      case GL_3D_COLOR:
74cdc920a0Smrg	 ctx->Feedback._Mask = (FB_3D | FB_COLOR);
757117f1b4Smrg	 break;
767117f1b4Smrg      case GL_3D_COLOR_TEXTURE:
77cdc920a0Smrg	 ctx->Feedback._Mask = (FB_3D | FB_COLOR | FB_TEXTURE);
787117f1b4Smrg	 break;
797117f1b4Smrg      case GL_4D_COLOR_TEXTURE:
80cdc920a0Smrg	 ctx->Feedback._Mask = (FB_3D | FB_4D | FB_COLOR | FB_TEXTURE);
817117f1b4Smrg	 break;
827117f1b4Smrg      default:
837117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
847117f1b4Smrg	 return;
857117f1b4Smrg   }
867117f1b4Smrg
877ec681f3Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE, 0); /* Always flush */
887117f1b4Smrg   ctx->Feedback.Type = type;
897117f1b4Smrg   ctx->Feedback.BufferSize = size;
907117f1b4Smrg   ctx->Feedback.Buffer = buffer;
9101e04c3fSmrg   ctx->Feedback.Count = 0;	              /* Because of this. */
927117f1b4Smrg}
937117f1b4Smrg
947117f1b4Smrg
95af69d88dSmrgvoid GLAPIENTRY
967117f1b4Smrg_mesa_PassThrough( GLfloat token )
977117f1b4Smrg{
987117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
997117f1b4Smrg
1007117f1b4Smrg   if (ctx->RenderMode==GL_FEEDBACK) {
1017ec681f3Smrg      FLUSH_VERTICES(ctx, 0, 0);
1024a49301eSmrg      _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
1034a49301eSmrg      _mesa_feedback_token( ctx, token );
1047117f1b4Smrg   }
1057117f1b4Smrg}
1067117f1b4Smrg
1077117f1b4Smrg
1084a49301eSmrg/**
1097117f1b4Smrg * Put a vertex into the feedback buffer.
1107117f1b4Smrg */
1114a49301eSmrgvoid
1123464ebd5Sriastradh_mesa_feedback_vertex(struct gl_context *ctx,
1134a49301eSmrg                      const GLfloat win[4],
1144a49301eSmrg                      const GLfloat color[4],
1154a49301eSmrg                      const GLfloat texcoord[4])
1167117f1b4Smrg{
1174a49301eSmrg   _mesa_feedback_token( ctx, win[0] );
1184a49301eSmrg   _mesa_feedback_token( ctx, win[1] );
1197117f1b4Smrg   if (ctx->Feedback._Mask & FB_3D) {
1204a49301eSmrg      _mesa_feedback_token( ctx, win[2] );
1217117f1b4Smrg   }
1227117f1b4Smrg   if (ctx->Feedback._Mask & FB_4D) {
1234a49301eSmrg      _mesa_feedback_token( ctx, win[3] );
1247117f1b4Smrg   }
1257117f1b4Smrg   if (ctx->Feedback._Mask & FB_COLOR) {
1264a49301eSmrg      _mesa_feedback_token( ctx, color[0] );
1274a49301eSmrg      _mesa_feedback_token( ctx, color[1] );
1284a49301eSmrg      _mesa_feedback_token( ctx, color[2] );
1294a49301eSmrg      _mesa_feedback_token( ctx, color[3] );
1307117f1b4Smrg   }
1317117f1b4Smrg   if (ctx->Feedback._Mask & FB_TEXTURE) {
1324a49301eSmrg      _mesa_feedback_token( ctx, texcoord[0] );
1334a49301eSmrg      _mesa_feedback_token( ctx, texcoord[1] );
1344a49301eSmrg      _mesa_feedback_token( ctx, texcoord[2] );
1354a49301eSmrg      _mesa_feedback_token( ctx, texcoord[3] );
1367117f1b4Smrg   }
1377117f1b4Smrg}
1387117f1b4Smrg
1397117f1b4Smrg
1407117f1b4Smrg/**********************************************************************/
1417117f1b4Smrg/** \name Selection */
1427117f1b4Smrg/*@{*/
1437117f1b4Smrg
1447117f1b4Smrg/**
1457117f1b4Smrg * Establish a buffer for selection mode values.
1467117f1b4Smrg *
1477117f1b4Smrg * \param size buffer size.
1487117f1b4Smrg * \param buffer buffer.
1497117f1b4Smrg *
1507117f1b4Smrg * \sa glSelectBuffer().
1517117f1b4Smrg *
1527117f1b4Smrg * \note this function can't be put in a display list.
1537117f1b4Smrg *
1547117f1b4Smrg * Verifies we're not in selection mode, flushes the vertices and initialize
1553464ebd5Sriastradh * the fields in __struct gl_contextRec::Select with the given buffer.
1567117f1b4Smrg */
157af69d88dSmrgvoid GLAPIENTRY
1587117f1b4Smrg_mesa_SelectBuffer( GLsizei size, GLuint *buffer )
1597117f1b4Smrg{
1607117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1617117f1b4Smrg
1623464ebd5Sriastradh   if (size < 0) {
1633464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "glSelectBuffer(size)");
1643464ebd5Sriastradh      return;
1653464ebd5Sriastradh   }
1663464ebd5Sriastradh
1677117f1b4Smrg   if (ctx->RenderMode==GL_SELECT) {
1687117f1b4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
1697117f1b4Smrg      return;			/* KW: added return */
1707117f1b4Smrg   }
1717117f1b4Smrg
1727ec681f3Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE, 0);
1737117f1b4Smrg   ctx->Select.Buffer = buffer;
1747117f1b4Smrg   ctx->Select.BufferSize = size;
1757117f1b4Smrg   ctx->Select.BufferCount = 0;
1767117f1b4Smrg   ctx->Select.HitFlag = GL_FALSE;
1777117f1b4Smrg   ctx->Select.HitMinZ = 1.0;
1787117f1b4Smrg   ctx->Select.HitMaxZ = 0.0;
1797117f1b4Smrg}
1807117f1b4Smrg
1817117f1b4Smrg
1827117f1b4Smrg/**
1837117f1b4Smrg * Write a value of a record into the selection buffer.
1847117f1b4Smrg *
1854a49301eSmrg * \param ctx GL context.
1864a49301eSmrg * \param value value.
1877117f1b4Smrg *
1887117f1b4Smrg * Verifies there is free space in the buffer to write the value and
1897117f1b4Smrg * increments the pointer.
1907117f1b4Smrg */
191af69d88dSmrgstatic inline void
1923464ebd5Sriastradhwrite_record(struct gl_context *ctx, GLuint value)
1934a49301eSmrg{
1944a49301eSmrg   if (ctx->Select.BufferCount < ctx->Select.BufferSize) {
1954a49301eSmrg      ctx->Select.Buffer[ctx->Select.BufferCount] = value;
1964a49301eSmrg   }
1974a49301eSmrg   ctx->Select.BufferCount++;
1984a49301eSmrg}
1997117f1b4Smrg
2007117f1b4Smrg
2017117f1b4Smrg/**
2027117f1b4Smrg * Update the hit flag and the maximum and minimum depth values.
2037117f1b4Smrg *
2047117f1b4Smrg * \param ctx GL context.
2057117f1b4Smrg * \param z depth.
2067117f1b4Smrg *
2077117f1b4Smrg * Sets gl_selection::HitFlag and updates gl_selection::HitMinZ and
2087117f1b4Smrg * gl_selection::HitMaxZ.
2097117f1b4Smrg */
2104a49301eSmrgvoid
2113464ebd5Sriastradh_mesa_update_hitflag(struct gl_context *ctx, GLfloat z)
2127117f1b4Smrg{
2137117f1b4Smrg   ctx->Select.HitFlag = GL_TRUE;
2147117f1b4Smrg   if (z < ctx->Select.HitMinZ) {
2157117f1b4Smrg      ctx->Select.HitMinZ = z;
2167117f1b4Smrg   }
2177117f1b4Smrg   if (z > ctx->Select.HitMaxZ) {
2187117f1b4Smrg      ctx->Select.HitMaxZ = z;
2197117f1b4Smrg   }
2207117f1b4Smrg}
2217117f1b4Smrg
2227117f1b4Smrg
2237117f1b4Smrg/**
2247117f1b4Smrg * Write the hit record.
2257117f1b4Smrg *
2267117f1b4Smrg * \param ctx GL context.
2277117f1b4Smrg *
2287117f1b4Smrg * Write the hit record, i.e., the number of names in the stack, the minimum and
2297117f1b4Smrg * maximum depth values and the number of names in the name stack at the time
2307117f1b4Smrg * of the event. Resets the hit flag.
2317117f1b4Smrg *
2327117f1b4Smrg * \sa gl_selection.
2337117f1b4Smrg */
2344a49301eSmrgstatic void
2353464ebd5Sriastradhwrite_hit_record(struct gl_context *ctx)
2367117f1b4Smrg{
2377117f1b4Smrg   GLuint i;
2387117f1b4Smrg   GLuint zmin, zmax, zscale = (~0u);
2397117f1b4Smrg
2407117f1b4Smrg   /* HitMinZ and HitMaxZ are in [0,1].  Multiply these values by */
2417117f1b4Smrg   /* 2^32-1 and round to nearest unsigned integer. */
2427117f1b4Smrg
2437117f1b4Smrg   assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */
2447117f1b4Smrg   zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
2457117f1b4Smrg   zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
2467117f1b4Smrg
2474a49301eSmrg   write_record( ctx, ctx->Select.NameStackDepth );
2484a49301eSmrg   write_record( ctx, zmin );
2494a49301eSmrg   write_record( ctx, zmax );
2507117f1b4Smrg   for (i = 0; i < ctx->Select.NameStackDepth; i++) {
2514a49301eSmrg      write_record( ctx, ctx->Select.NameStack[i] );
2527117f1b4Smrg   }
2537117f1b4Smrg
2547117f1b4Smrg   ctx->Select.Hits++;
2557117f1b4Smrg   ctx->Select.HitFlag = GL_FALSE;
2567117f1b4Smrg   ctx->Select.HitMinZ = 1.0;
2577117f1b4Smrg   ctx->Select.HitMaxZ = -1.0;
2587117f1b4Smrg}
2597117f1b4Smrg
2607117f1b4Smrg
2617117f1b4Smrg/**
2627117f1b4Smrg * Initialize the name stack.
2637117f1b4Smrg *
2647117f1b4Smrg * Verifies we are in select mode and resets the name stack depth and resets
2657117f1b4Smrg * the hit record data in gl_selection. Marks new render mode in
2663464ebd5Sriastradh * __struct gl_contextRec::NewState.
2677117f1b4Smrg */
268af69d88dSmrgvoid GLAPIENTRY
2697117f1b4Smrg_mesa_InitNames( void )
2707117f1b4Smrg{
2717117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2727ec681f3Smrg   FLUSH_VERTICES(ctx, 0, 0);
2737117f1b4Smrg
2747117f1b4Smrg   /* Record the hit before the HitFlag is wiped out again. */
2757117f1b4Smrg   if (ctx->RenderMode == GL_SELECT) {
2767117f1b4Smrg      if (ctx->Select.HitFlag) {
2777117f1b4Smrg         write_hit_record( ctx );
2787117f1b4Smrg      }
2797117f1b4Smrg   }
2807117f1b4Smrg   ctx->Select.NameStackDepth = 0;
2817117f1b4Smrg   ctx->Select.HitFlag = GL_FALSE;
2827117f1b4Smrg   ctx->Select.HitMinZ = 1.0;
2837117f1b4Smrg   ctx->Select.HitMaxZ = 0.0;
2847117f1b4Smrg   ctx->NewState |= _NEW_RENDERMODE;
2857117f1b4Smrg}
2867117f1b4Smrg
2877117f1b4Smrg
2887117f1b4Smrg/**
2897117f1b4Smrg * Load the top-most name of the name stack.
2907117f1b4Smrg *
2917117f1b4Smrg * \param name name.
2927117f1b4Smrg *
2937117f1b4Smrg * Verifies we are in selection mode and that the name stack is not empty.
2947117f1b4Smrg * Flushes vertices. If there is a hit flag writes it (via write_hit_record()),
2957117f1b4Smrg * and replace the top-most name in the stack.
2967117f1b4Smrg *
2973464ebd5Sriastradh * sa __struct gl_contextRec::Select.
2987117f1b4Smrg */
299af69d88dSmrgvoid GLAPIENTRY
3007117f1b4Smrg_mesa_LoadName( GLuint name )
3017117f1b4Smrg{
3027117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
3037117f1b4Smrg
3047117f1b4Smrg   if (ctx->RenderMode != GL_SELECT) {
3057117f1b4Smrg      return;
3067117f1b4Smrg   }
3077117f1b4Smrg   if (ctx->Select.NameStackDepth == 0) {
3087117f1b4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
3097117f1b4Smrg      return;
3107117f1b4Smrg   }
3117117f1b4Smrg
3127ec681f3Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE, 0);
3137117f1b4Smrg
3147117f1b4Smrg   if (ctx->Select.HitFlag) {
3157117f1b4Smrg      write_hit_record( ctx );
3167117f1b4Smrg   }
3177117f1b4Smrg   if (ctx->Select.NameStackDepth < MAX_NAME_STACK_DEPTH) {
3187117f1b4Smrg      ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name;
3197117f1b4Smrg   }
3207117f1b4Smrg   else {
3217117f1b4Smrg      ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name;
3227117f1b4Smrg   }
3237117f1b4Smrg}
3247117f1b4Smrg
3257117f1b4Smrg
3267117f1b4Smrg/**
3277117f1b4Smrg * Push a name into the name stack.
3287117f1b4Smrg *
3297117f1b4Smrg * \param name name.
3307117f1b4Smrg *
3317117f1b4Smrg * Verifies we are in selection mode and that the name stack is not full.
3327117f1b4Smrg * Flushes vertices. If there is a hit flag writes it (via write_hit_record()),
3337117f1b4Smrg * and adds the name to the top of the name stack.
3347117f1b4Smrg *
3353464ebd5Sriastradh * sa __struct gl_contextRec::Select.
3367117f1b4Smrg */
337af69d88dSmrgvoid GLAPIENTRY
3387117f1b4Smrg_mesa_PushName( GLuint name )
3397117f1b4Smrg{
3407117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
3417117f1b4Smrg
3427117f1b4Smrg   if (ctx->RenderMode != GL_SELECT) {
3437117f1b4Smrg      return;
3447117f1b4Smrg   }
3457117f1b4Smrg
3467ec681f3Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE, 0);
3477117f1b4Smrg   if (ctx->Select.HitFlag) {
3487117f1b4Smrg      write_hit_record( ctx );
3497117f1b4Smrg   }
3507117f1b4Smrg   if (ctx->Select.NameStackDepth >= MAX_NAME_STACK_DEPTH) {
3517117f1b4Smrg      _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
3527117f1b4Smrg   }
3537117f1b4Smrg   else
3547117f1b4Smrg      ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
3557117f1b4Smrg}
3567117f1b4Smrg
3577117f1b4Smrg
3587117f1b4Smrg/**
3597117f1b4Smrg * Pop a name into the name stack.
3607117f1b4Smrg *
3617117f1b4Smrg * Verifies we are in selection mode and that the name stack is not empty.
3627117f1b4Smrg * Flushes vertices. If there is a hit flag writes it (via write_hit_record()),
3637117f1b4Smrg * and removes top-most name in the name stack.
3647117f1b4Smrg *
3653464ebd5Sriastradh * sa __struct gl_contextRec::Select.
3667117f1b4Smrg */
367af69d88dSmrgvoid GLAPIENTRY
3687117f1b4Smrg_mesa_PopName( void )
3697117f1b4Smrg{
3707117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
3717117f1b4Smrg
3727117f1b4Smrg   if (ctx->RenderMode != GL_SELECT) {
3737117f1b4Smrg      return;
3747117f1b4Smrg   }
3757117f1b4Smrg
3767ec681f3Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE, 0);
3777117f1b4Smrg   if (ctx->Select.HitFlag) {
3787117f1b4Smrg      write_hit_record( ctx );
3797117f1b4Smrg   }
3807117f1b4Smrg   if (ctx->Select.NameStackDepth == 0) {
3817117f1b4Smrg      _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
3827117f1b4Smrg   }
3837117f1b4Smrg   else
3847117f1b4Smrg      ctx->Select.NameStackDepth--;
3857117f1b4Smrg}
3867117f1b4Smrg
3877117f1b4Smrg/*@}*/
3887117f1b4Smrg
3897117f1b4Smrg
3907117f1b4Smrg/**********************************************************************/
3917117f1b4Smrg/** \name Render Mode */
3927117f1b4Smrg/*@{*/
3937117f1b4Smrg
3947117f1b4Smrg/**
3957117f1b4Smrg * Set rasterization mode.
3967117f1b4Smrg *
3977117f1b4Smrg * \param mode rasterization mode.
3987117f1b4Smrg *
3997117f1b4Smrg * \note this function can't be put in a display list.
4007117f1b4Smrg *
4017117f1b4Smrg * \sa glRenderMode().
4027117f1b4Smrg *
4037117f1b4Smrg * Flushes the vertices and do the necessary cleanup according to the previous
4047117f1b4Smrg * rasterization mode, such as writing the hit record or resent the select
4057117f1b4Smrg * buffer index when exiting the select mode. Updates
4063464ebd5Sriastradh * __struct gl_contextRec::RenderMode and notifies the driver via the
4077117f1b4Smrg * dd_function_table::RenderMode callback.
4087117f1b4Smrg */
409af69d88dSmrgGLint GLAPIENTRY
4107117f1b4Smrg_mesa_RenderMode( GLenum mode )
4117117f1b4Smrg{
4127117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
4137117f1b4Smrg   GLint result;
4147117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
4157117f1b4Smrg
4167117f1b4Smrg   if (MESA_VERBOSE & VERBOSE_API)
41701e04c3fSmrg      _mesa_debug(ctx, "glRenderMode %s\n", _mesa_enum_to_string(mode));
4187117f1b4Smrg
4197ec681f3Smrg   FLUSH_VERTICES(ctx, _NEW_RENDERMODE | _NEW_FF_VERT_PROGRAM |
4207ec681f3Smrg                  _NEW_FF_FRAG_PROGRAM, 0);
4217117f1b4Smrg
4227117f1b4Smrg   switch (ctx->RenderMode) {
4237117f1b4Smrg      case GL_RENDER:
4247117f1b4Smrg	 result = 0;
4257117f1b4Smrg	 break;
4267117f1b4Smrg      case GL_SELECT:
4277117f1b4Smrg	 if (ctx->Select.HitFlag) {
4287117f1b4Smrg	    write_hit_record( ctx );
4297117f1b4Smrg	 }
4307117f1b4Smrg	 if (ctx->Select.BufferCount > ctx->Select.BufferSize) {
4317117f1b4Smrg	    /* overflow */
4327ec681f3Smrg#ifndef NDEBUG
4337117f1b4Smrg            _mesa_warning(ctx, "Feedback buffer overflow");
4347117f1b4Smrg#endif
4357117f1b4Smrg	    result = -1;
4367117f1b4Smrg	 }
4377117f1b4Smrg	 else {
4387117f1b4Smrg	    result = ctx->Select.Hits;
4397117f1b4Smrg	 }
4407117f1b4Smrg	 ctx->Select.BufferCount = 0;
4417117f1b4Smrg	 ctx->Select.Hits = 0;
4427117f1b4Smrg	 ctx->Select.NameStackDepth = 0;
4437117f1b4Smrg	 break;
4447117f1b4Smrg      case GL_FEEDBACK:
4457117f1b4Smrg	 if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
4467117f1b4Smrg	    /* overflow */
4477117f1b4Smrg	    result = -1;
4487117f1b4Smrg	 }
4497117f1b4Smrg	 else {
4507117f1b4Smrg	    result = ctx->Feedback.Count;
4517117f1b4Smrg	 }
4527117f1b4Smrg	 ctx->Feedback.Count = 0;
4537117f1b4Smrg	 break;
4547117f1b4Smrg      default:
4557117f1b4Smrg	 _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
4567117f1b4Smrg	 return 0;
4577117f1b4Smrg   }
4587117f1b4Smrg
4597117f1b4Smrg   switch (mode) {
4607117f1b4Smrg      case GL_RENDER:
4617117f1b4Smrg         break;
4627117f1b4Smrg      case GL_SELECT:
4637117f1b4Smrg	 if (ctx->Select.BufferSize==0) {
4647117f1b4Smrg	    /* haven't called glSelectBuffer yet */
4657117f1b4Smrg	    _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
4667117f1b4Smrg	 }
4677117f1b4Smrg	 break;
4687117f1b4Smrg      case GL_FEEDBACK:
4697117f1b4Smrg	 if (ctx->Feedback.BufferSize==0) {
4707117f1b4Smrg	    /* haven't called glFeedbackBuffer yet */
4717117f1b4Smrg	    _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
4727117f1b4Smrg	 }
4737117f1b4Smrg	 break;
4747117f1b4Smrg      default:
4757117f1b4Smrg	 _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
4767117f1b4Smrg	 return 0;
4777117f1b4Smrg   }
4787117f1b4Smrg
4797117f1b4Smrg   ctx->RenderMode = mode;
4807117f1b4Smrg   if (ctx->Driver.RenderMode)
4817117f1b4Smrg      ctx->Driver.RenderMode( ctx, mode );
4827117f1b4Smrg
4837117f1b4Smrg   return result;
4847117f1b4Smrg}
4857117f1b4Smrg
4867117f1b4Smrg/*@}*/
4877117f1b4Smrg
4887117f1b4Smrg
4897117f1b4Smrg/**********************************************************************/
4907117f1b4Smrg/** \name Initialization */
4917117f1b4Smrg/*@{*/
4927117f1b4Smrg
4937117f1b4Smrg/**
4947117f1b4Smrg * Initialize context feedback data.
4957117f1b4Smrg */
4963464ebd5Sriastradhvoid _mesa_init_feedback( struct gl_context * ctx )
4977117f1b4Smrg{
4987117f1b4Smrg   /* Feedback */
4997117f1b4Smrg   ctx->Feedback.Type = GL_2D;   /* TODO: verify */
5007117f1b4Smrg   ctx->Feedback.Buffer = NULL;
5017117f1b4Smrg   ctx->Feedback.BufferSize = 0;
5027117f1b4Smrg   ctx->Feedback.Count = 0;
5037117f1b4Smrg
5047117f1b4Smrg   /* Selection/picking */
5057117f1b4Smrg   ctx->Select.Buffer = NULL;
5067117f1b4Smrg   ctx->Select.BufferSize = 0;
5077117f1b4Smrg   ctx->Select.BufferCount = 0;
5087117f1b4Smrg   ctx->Select.Hits = 0;
5097117f1b4Smrg   ctx->Select.NameStackDepth = 0;
5107117f1b4Smrg
5117117f1b4Smrg   /* Miscellaneous */
5127117f1b4Smrg   ctx->RenderMode = GL_RENDER;
5137117f1b4Smrg}
5147117f1b4Smrg
5157117f1b4Smrg/*@}*/
516