1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg/** 27848b8605Smrg * \file feedback.c 28848b8605Smrg * Selection and feedback modes functions. 29848b8605Smrg */ 30848b8605Smrg 31848b8605Smrg 32848b8605Smrg#include "glheader.h" 33848b8605Smrg#include "context.h" 34848b8605Smrg#include "enums.h" 35848b8605Smrg#include "feedback.h" 36848b8605Smrg#include "macros.h" 37848b8605Smrg#include "mtypes.h" 38848b8605Smrg 39848b8605Smrg 40848b8605Smrg#define FB_3D 0x01 41848b8605Smrg#define FB_4D 0x02 42848b8605Smrg#define FB_COLOR 0x04 43848b8605Smrg#define FB_TEXTURE 0X08 44848b8605Smrg 45848b8605Smrg 46848b8605Smrg 47848b8605Smrgvoid GLAPIENTRY 48848b8605Smrg_mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer ) 49848b8605Smrg{ 50848b8605Smrg GET_CURRENT_CONTEXT(ctx); 51848b8605Smrg 52848b8605Smrg if (ctx->RenderMode==GL_FEEDBACK) { 53848b8605Smrg _mesa_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" ); 54848b8605Smrg return; 55848b8605Smrg } 56848b8605Smrg if (size<0) { 57848b8605Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" ); 58848b8605Smrg return; 59848b8605Smrg } 60848b8605Smrg if (!buffer && size > 0) { 61848b8605Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" ); 62848b8605Smrg ctx->Feedback.BufferSize = 0; 63848b8605Smrg return; 64848b8605Smrg } 65848b8605Smrg 66848b8605Smrg switch (type) { 67848b8605Smrg case GL_2D: 68848b8605Smrg ctx->Feedback._Mask = 0; 69848b8605Smrg break; 70848b8605Smrg case GL_3D: 71848b8605Smrg ctx->Feedback._Mask = FB_3D; 72848b8605Smrg break; 73848b8605Smrg case GL_3D_COLOR: 74848b8605Smrg ctx->Feedback._Mask = (FB_3D | FB_COLOR); 75848b8605Smrg break; 76848b8605Smrg case GL_3D_COLOR_TEXTURE: 77848b8605Smrg ctx->Feedback._Mask = (FB_3D | FB_COLOR | FB_TEXTURE); 78848b8605Smrg break; 79848b8605Smrg case GL_4D_COLOR_TEXTURE: 80848b8605Smrg ctx->Feedback._Mask = (FB_3D | FB_4D | FB_COLOR | FB_TEXTURE); 81848b8605Smrg break; 82848b8605Smrg default: 83848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" ); 84848b8605Smrg return; 85848b8605Smrg } 86848b8605Smrg 87848b8605Smrg FLUSH_VERTICES(ctx, _NEW_RENDERMODE); /* Always flush */ 88848b8605Smrg ctx->Feedback.Type = type; 89848b8605Smrg ctx->Feedback.BufferSize = size; 90848b8605Smrg ctx->Feedback.Buffer = buffer; 91b8e80941Smrg ctx->Feedback.Count = 0; /* Because of this. */ 92848b8605Smrg} 93848b8605Smrg 94848b8605Smrg 95848b8605Smrgvoid GLAPIENTRY 96848b8605Smrg_mesa_PassThrough( GLfloat token ) 97848b8605Smrg{ 98848b8605Smrg GET_CURRENT_CONTEXT(ctx); 99848b8605Smrg 100848b8605Smrg if (ctx->RenderMode==GL_FEEDBACK) { 101848b8605Smrg FLUSH_VERTICES(ctx, 0); 102848b8605Smrg _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN ); 103848b8605Smrg _mesa_feedback_token( ctx, token ); 104848b8605Smrg } 105848b8605Smrg} 106848b8605Smrg 107848b8605Smrg 108848b8605Smrg/** 109848b8605Smrg * Put a vertex into the feedback buffer. 110848b8605Smrg */ 111848b8605Smrgvoid 112848b8605Smrg_mesa_feedback_vertex(struct gl_context *ctx, 113848b8605Smrg const GLfloat win[4], 114848b8605Smrg const GLfloat color[4], 115848b8605Smrg const GLfloat texcoord[4]) 116848b8605Smrg{ 117848b8605Smrg _mesa_feedback_token( ctx, win[0] ); 118848b8605Smrg _mesa_feedback_token( ctx, win[1] ); 119848b8605Smrg if (ctx->Feedback._Mask & FB_3D) { 120848b8605Smrg _mesa_feedback_token( ctx, win[2] ); 121848b8605Smrg } 122848b8605Smrg if (ctx->Feedback._Mask & FB_4D) { 123848b8605Smrg _mesa_feedback_token( ctx, win[3] ); 124848b8605Smrg } 125848b8605Smrg if (ctx->Feedback._Mask & FB_COLOR) { 126848b8605Smrg _mesa_feedback_token( ctx, color[0] ); 127848b8605Smrg _mesa_feedback_token( ctx, color[1] ); 128848b8605Smrg _mesa_feedback_token( ctx, color[2] ); 129848b8605Smrg _mesa_feedback_token( ctx, color[3] ); 130848b8605Smrg } 131848b8605Smrg if (ctx->Feedback._Mask & FB_TEXTURE) { 132848b8605Smrg _mesa_feedback_token( ctx, texcoord[0] ); 133848b8605Smrg _mesa_feedback_token( ctx, texcoord[1] ); 134848b8605Smrg _mesa_feedback_token( ctx, texcoord[2] ); 135848b8605Smrg _mesa_feedback_token( ctx, texcoord[3] ); 136848b8605Smrg } 137848b8605Smrg} 138848b8605Smrg 139848b8605Smrg 140848b8605Smrg/**********************************************************************/ 141848b8605Smrg/** \name Selection */ 142848b8605Smrg/*@{*/ 143848b8605Smrg 144848b8605Smrg/** 145848b8605Smrg * Establish a buffer for selection mode values. 146848b8605Smrg * 147848b8605Smrg * \param size buffer size. 148848b8605Smrg * \param buffer buffer. 149848b8605Smrg * 150848b8605Smrg * \sa glSelectBuffer(). 151848b8605Smrg * 152848b8605Smrg * \note this function can't be put in a display list. 153848b8605Smrg * 154848b8605Smrg * Verifies we're not in selection mode, flushes the vertices and initialize 155848b8605Smrg * the fields in __struct gl_contextRec::Select with the given buffer. 156848b8605Smrg */ 157848b8605Smrgvoid GLAPIENTRY 158848b8605Smrg_mesa_SelectBuffer( GLsizei size, GLuint *buffer ) 159848b8605Smrg{ 160848b8605Smrg GET_CURRENT_CONTEXT(ctx); 161848b8605Smrg 162848b8605Smrg if (size < 0) { 163848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glSelectBuffer(size)"); 164848b8605Smrg return; 165848b8605Smrg } 166848b8605Smrg 167848b8605Smrg if (ctx->RenderMode==GL_SELECT) { 168848b8605Smrg _mesa_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" ); 169848b8605Smrg return; /* KW: added return */ 170848b8605Smrg } 171848b8605Smrg 172848b8605Smrg FLUSH_VERTICES(ctx, _NEW_RENDERMODE); 173848b8605Smrg ctx->Select.Buffer = buffer; 174848b8605Smrg ctx->Select.BufferSize = size; 175848b8605Smrg ctx->Select.BufferCount = 0; 176848b8605Smrg ctx->Select.HitFlag = GL_FALSE; 177848b8605Smrg ctx->Select.HitMinZ = 1.0; 178848b8605Smrg ctx->Select.HitMaxZ = 0.0; 179848b8605Smrg} 180848b8605Smrg 181848b8605Smrg 182848b8605Smrg/** 183848b8605Smrg * Write a value of a record into the selection buffer. 184848b8605Smrg * 185848b8605Smrg * \param ctx GL context. 186848b8605Smrg * \param value value. 187848b8605Smrg * 188848b8605Smrg * Verifies there is free space in the buffer to write the value and 189848b8605Smrg * increments the pointer. 190848b8605Smrg */ 191848b8605Smrgstatic inline void 192848b8605Smrgwrite_record(struct gl_context *ctx, GLuint value) 193848b8605Smrg{ 194848b8605Smrg if (ctx->Select.BufferCount < ctx->Select.BufferSize) { 195848b8605Smrg ctx->Select.Buffer[ctx->Select.BufferCount] = value; 196848b8605Smrg } 197848b8605Smrg ctx->Select.BufferCount++; 198848b8605Smrg} 199848b8605Smrg 200848b8605Smrg 201848b8605Smrg/** 202848b8605Smrg * Update the hit flag and the maximum and minimum depth values. 203848b8605Smrg * 204848b8605Smrg * \param ctx GL context. 205848b8605Smrg * \param z depth. 206848b8605Smrg * 207848b8605Smrg * Sets gl_selection::HitFlag and updates gl_selection::HitMinZ and 208848b8605Smrg * gl_selection::HitMaxZ. 209848b8605Smrg */ 210848b8605Smrgvoid 211848b8605Smrg_mesa_update_hitflag(struct gl_context *ctx, GLfloat z) 212848b8605Smrg{ 213848b8605Smrg ctx->Select.HitFlag = GL_TRUE; 214848b8605Smrg if (z < ctx->Select.HitMinZ) { 215848b8605Smrg ctx->Select.HitMinZ = z; 216848b8605Smrg } 217848b8605Smrg if (z > ctx->Select.HitMaxZ) { 218848b8605Smrg ctx->Select.HitMaxZ = z; 219848b8605Smrg } 220848b8605Smrg} 221848b8605Smrg 222848b8605Smrg 223848b8605Smrg/** 224848b8605Smrg * Write the hit record. 225848b8605Smrg * 226848b8605Smrg * \param ctx GL context. 227848b8605Smrg * 228848b8605Smrg * Write the hit record, i.e., the number of names in the stack, the minimum and 229848b8605Smrg * maximum depth values and the number of names in the name stack at the time 230848b8605Smrg * of the event. Resets the hit flag. 231848b8605Smrg * 232848b8605Smrg * \sa gl_selection. 233848b8605Smrg */ 234848b8605Smrgstatic void 235848b8605Smrgwrite_hit_record(struct gl_context *ctx) 236848b8605Smrg{ 237848b8605Smrg GLuint i; 238848b8605Smrg GLuint zmin, zmax, zscale = (~0u); 239848b8605Smrg 240848b8605Smrg /* HitMinZ and HitMaxZ are in [0,1]. Multiply these values by */ 241848b8605Smrg /* 2^32-1 and round to nearest unsigned integer. */ 242848b8605Smrg 243848b8605Smrg assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */ 244848b8605Smrg zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ); 245848b8605Smrg zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ); 246848b8605Smrg 247848b8605Smrg write_record( ctx, ctx->Select.NameStackDepth ); 248848b8605Smrg write_record( ctx, zmin ); 249848b8605Smrg write_record( ctx, zmax ); 250848b8605Smrg for (i = 0; i < ctx->Select.NameStackDepth; i++) { 251848b8605Smrg write_record( ctx, ctx->Select.NameStack[i] ); 252848b8605Smrg } 253848b8605Smrg 254848b8605Smrg ctx->Select.Hits++; 255848b8605Smrg ctx->Select.HitFlag = GL_FALSE; 256848b8605Smrg ctx->Select.HitMinZ = 1.0; 257848b8605Smrg ctx->Select.HitMaxZ = -1.0; 258848b8605Smrg} 259848b8605Smrg 260848b8605Smrg 261848b8605Smrg/** 262848b8605Smrg * Initialize the name stack. 263848b8605Smrg * 264848b8605Smrg * Verifies we are in select mode and resets the name stack depth and resets 265848b8605Smrg * the hit record data in gl_selection. Marks new render mode in 266848b8605Smrg * __struct gl_contextRec::NewState. 267848b8605Smrg */ 268848b8605Smrgvoid GLAPIENTRY 269848b8605Smrg_mesa_InitNames( void ) 270848b8605Smrg{ 271848b8605Smrg GET_CURRENT_CONTEXT(ctx); 272848b8605Smrg FLUSH_VERTICES(ctx, 0); 273848b8605Smrg 274848b8605Smrg /* Record the hit before the HitFlag is wiped out again. */ 275848b8605Smrg if (ctx->RenderMode == GL_SELECT) { 276848b8605Smrg if (ctx->Select.HitFlag) { 277848b8605Smrg write_hit_record( ctx ); 278848b8605Smrg } 279848b8605Smrg } 280848b8605Smrg ctx->Select.NameStackDepth = 0; 281848b8605Smrg ctx->Select.HitFlag = GL_FALSE; 282848b8605Smrg ctx->Select.HitMinZ = 1.0; 283848b8605Smrg ctx->Select.HitMaxZ = 0.0; 284848b8605Smrg ctx->NewState |= _NEW_RENDERMODE; 285848b8605Smrg} 286848b8605Smrg 287848b8605Smrg 288848b8605Smrg/** 289848b8605Smrg * Load the top-most name of the name stack. 290848b8605Smrg * 291848b8605Smrg * \param name name. 292848b8605Smrg * 293848b8605Smrg * Verifies we are in selection mode and that the name stack is not empty. 294848b8605Smrg * Flushes vertices. If there is a hit flag writes it (via write_hit_record()), 295848b8605Smrg * and replace the top-most name in the stack. 296848b8605Smrg * 297848b8605Smrg * sa __struct gl_contextRec::Select. 298848b8605Smrg */ 299848b8605Smrgvoid GLAPIENTRY 300848b8605Smrg_mesa_LoadName( GLuint name ) 301848b8605Smrg{ 302848b8605Smrg GET_CURRENT_CONTEXT(ctx); 303848b8605Smrg 304848b8605Smrg if (ctx->RenderMode != GL_SELECT) { 305848b8605Smrg return; 306848b8605Smrg } 307848b8605Smrg if (ctx->Select.NameStackDepth == 0) { 308848b8605Smrg _mesa_error( ctx, GL_INVALID_OPERATION, "glLoadName" ); 309848b8605Smrg return; 310848b8605Smrg } 311848b8605Smrg 312848b8605Smrg FLUSH_VERTICES(ctx, _NEW_RENDERMODE); 313848b8605Smrg 314848b8605Smrg if (ctx->Select.HitFlag) { 315848b8605Smrg write_hit_record( ctx ); 316848b8605Smrg } 317848b8605Smrg if (ctx->Select.NameStackDepth < MAX_NAME_STACK_DEPTH) { 318848b8605Smrg ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name; 319848b8605Smrg } 320848b8605Smrg else { 321848b8605Smrg ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name; 322848b8605Smrg } 323848b8605Smrg} 324848b8605Smrg 325848b8605Smrg 326848b8605Smrg/** 327848b8605Smrg * Push a name into the name stack. 328848b8605Smrg * 329848b8605Smrg * \param name name. 330848b8605Smrg * 331848b8605Smrg * Verifies we are in selection mode and that the name stack is not full. 332848b8605Smrg * Flushes vertices. If there is a hit flag writes it (via write_hit_record()), 333848b8605Smrg * and adds the name to the top of the name stack. 334848b8605Smrg * 335848b8605Smrg * sa __struct gl_contextRec::Select. 336848b8605Smrg */ 337848b8605Smrgvoid GLAPIENTRY 338848b8605Smrg_mesa_PushName( GLuint name ) 339848b8605Smrg{ 340848b8605Smrg GET_CURRENT_CONTEXT(ctx); 341848b8605Smrg 342848b8605Smrg if (ctx->RenderMode != GL_SELECT) { 343848b8605Smrg return; 344848b8605Smrg } 345848b8605Smrg 346848b8605Smrg FLUSH_VERTICES(ctx, _NEW_RENDERMODE); 347848b8605Smrg if (ctx->Select.HitFlag) { 348848b8605Smrg write_hit_record( ctx ); 349848b8605Smrg } 350848b8605Smrg if (ctx->Select.NameStackDepth >= MAX_NAME_STACK_DEPTH) { 351848b8605Smrg _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushName" ); 352848b8605Smrg } 353848b8605Smrg else 354848b8605Smrg ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name; 355848b8605Smrg} 356848b8605Smrg 357848b8605Smrg 358848b8605Smrg/** 359848b8605Smrg * Pop a name into the name stack. 360848b8605Smrg * 361848b8605Smrg * Verifies we are in selection mode and that the name stack is not empty. 362848b8605Smrg * Flushes vertices. If there is a hit flag writes it (via write_hit_record()), 363848b8605Smrg * and removes top-most name in the name stack. 364848b8605Smrg * 365848b8605Smrg * sa __struct gl_contextRec::Select. 366848b8605Smrg */ 367848b8605Smrgvoid GLAPIENTRY 368848b8605Smrg_mesa_PopName( void ) 369848b8605Smrg{ 370848b8605Smrg GET_CURRENT_CONTEXT(ctx); 371848b8605Smrg 372848b8605Smrg if (ctx->RenderMode != GL_SELECT) { 373848b8605Smrg return; 374848b8605Smrg } 375848b8605Smrg 376848b8605Smrg FLUSH_VERTICES(ctx, _NEW_RENDERMODE); 377848b8605Smrg if (ctx->Select.HitFlag) { 378848b8605Smrg write_hit_record( ctx ); 379848b8605Smrg } 380848b8605Smrg if (ctx->Select.NameStackDepth == 0) { 381848b8605Smrg _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopName" ); 382848b8605Smrg } 383848b8605Smrg else 384848b8605Smrg ctx->Select.NameStackDepth--; 385848b8605Smrg} 386848b8605Smrg 387848b8605Smrg/*@}*/ 388848b8605Smrg 389848b8605Smrg 390848b8605Smrg/**********************************************************************/ 391848b8605Smrg/** \name Render Mode */ 392848b8605Smrg/*@{*/ 393848b8605Smrg 394848b8605Smrg/** 395848b8605Smrg * Set rasterization mode. 396848b8605Smrg * 397848b8605Smrg * \param mode rasterization mode. 398848b8605Smrg * 399848b8605Smrg * \note this function can't be put in a display list. 400848b8605Smrg * 401848b8605Smrg * \sa glRenderMode(). 402848b8605Smrg * 403848b8605Smrg * Flushes the vertices and do the necessary cleanup according to the previous 404848b8605Smrg * rasterization mode, such as writing the hit record or resent the select 405848b8605Smrg * buffer index when exiting the select mode. Updates 406848b8605Smrg * __struct gl_contextRec::RenderMode and notifies the driver via the 407848b8605Smrg * dd_function_table::RenderMode callback. 408848b8605Smrg */ 409848b8605SmrgGLint GLAPIENTRY 410848b8605Smrg_mesa_RenderMode( GLenum mode ) 411848b8605Smrg{ 412848b8605Smrg GET_CURRENT_CONTEXT(ctx); 413848b8605Smrg GLint result; 414848b8605Smrg ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); 415848b8605Smrg 416848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 417b8e80941Smrg _mesa_debug(ctx, "glRenderMode %s\n", _mesa_enum_to_string(mode)); 418848b8605Smrg 419848b8605Smrg FLUSH_VERTICES(ctx, _NEW_RENDERMODE); 420848b8605Smrg 421848b8605Smrg switch (ctx->RenderMode) { 422848b8605Smrg case GL_RENDER: 423848b8605Smrg result = 0; 424848b8605Smrg break; 425848b8605Smrg case GL_SELECT: 426848b8605Smrg if (ctx->Select.HitFlag) { 427848b8605Smrg write_hit_record( ctx ); 428848b8605Smrg } 429848b8605Smrg if (ctx->Select.BufferCount > ctx->Select.BufferSize) { 430848b8605Smrg /* overflow */ 431848b8605Smrg#ifdef DEBUG 432848b8605Smrg _mesa_warning(ctx, "Feedback buffer overflow"); 433848b8605Smrg#endif 434848b8605Smrg result = -1; 435848b8605Smrg } 436848b8605Smrg else { 437848b8605Smrg result = ctx->Select.Hits; 438848b8605Smrg } 439848b8605Smrg ctx->Select.BufferCount = 0; 440848b8605Smrg ctx->Select.Hits = 0; 441848b8605Smrg ctx->Select.NameStackDepth = 0; 442848b8605Smrg break; 443848b8605Smrg case GL_FEEDBACK: 444848b8605Smrg if (ctx->Feedback.Count > ctx->Feedback.BufferSize) { 445848b8605Smrg /* overflow */ 446848b8605Smrg result = -1; 447848b8605Smrg } 448848b8605Smrg else { 449848b8605Smrg result = ctx->Feedback.Count; 450848b8605Smrg } 451848b8605Smrg ctx->Feedback.Count = 0; 452848b8605Smrg break; 453848b8605Smrg default: 454848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" ); 455848b8605Smrg return 0; 456848b8605Smrg } 457848b8605Smrg 458848b8605Smrg switch (mode) { 459848b8605Smrg case GL_RENDER: 460848b8605Smrg break; 461848b8605Smrg case GL_SELECT: 462848b8605Smrg if (ctx->Select.BufferSize==0) { 463848b8605Smrg /* haven't called glSelectBuffer yet */ 464848b8605Smrg _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" ); 465848b8605Smrg } 466848b8605Smrg break; 467848b8605Smrg case GL_FEEDBACK: 468848b8605Smrg if (ctx->Feedback.BufferSize==0) { 469848b8605Smrg /* haven't called glFeedbackBuffer yet */ 470848b8605Smrg _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" ); 471848b8605Smrg } 472848b8605Smrg break; 473848b8605Smrg default: 474848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" ); 475848b8605Smrg return 0; 476848b8605Smrg } 477848b8605Smrg 478848b8605Smrg ctx->RenderMode = mode; 479848b8605Smrg if (ctx->Driver.RenderMode) 480848b8605Smrg ctx->Driver.RenderMode( ctx, mode ); 481848b8605Smrg 482848b8605Smrg return result; 483848b8605Smrg} 484848b8605Smrg 485848b8605Smrg/*@}*/ 486848b8605Smrg 487848b8605Smrg 488848b8605Smrg/**********************************************************************/ 489848b8605Smrg/** \name Initialization */ 490848b8605Smrg/*@{*/ 491848b8605Smrg 492848b8605Smrg/** 493848b8605Smrg * Initialize context feedback data. 494848b8605Smrg */ 495848b8605Smrgvoid _mesa_init_feedback( struct gl_context * ctx ) 496848b8605Smrg{ 497848b8605Smrg /* Feedback */ 498848b8605Smrg ctx->Feedback.Type = GL_2D; /* TODO: verify */ 499848b8605Smrg ctx->Feedback.Buffer = NULL; 500848b8605Smrg ctx->Feedback.BufferSize = 0; 501848b8605Smrg ctx->Feedback.Count = 0; 502848b8605Smrg 503848b8605Smrg /* Selection/picking */ 504848b8605Smrg ctx->Select.Buffer = NULL; 505848b8605Smrg ctx->Select.BufferSize = 0; 506848b8605Smrg ctx->Select.BufferCount = 0; 507848b8605Smrg ctx->Select.Hits = 0; 508848b8605Smrg ctx->Select.NameStackDepth = 0; 509848b8605Smrg 510848b8605Smrg /* Miscellaneous */ 511848b8605Smrg ctx->RenderMode = GL_RENDER; 512848b8605Smrg} 513848b8605Smrg 514848b8605Smrg/*@}*/ 515