xref: /aosp_15_r20/external/mesa3d/src/mesa/main/feedback.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Mesa 3-D graphics library
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
6*61046927SAndroid Build Coastguard Worker  *
7*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
9*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
10*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
12*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
15*61046927SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
16*61046927SAndroid Build Coastguard Worker  *
17*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21*61046927SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22*61046927SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23*61046927SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
24*61046927SAndroid Build Coastguard Worker  */
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker /**
27*61046927SAndroid Build Coastguard Worker  * \file feedback.c
28*61046927SAndroid Build Coastguard Worker  * Selection and feedback modes functions.
29*61046927SAndroid Build Coastguard Worker  */
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
33*61046927SAndroid Build Coastguard Worker #include "c99_alloca.h"
34*61046927SAndroid Build Coastguard Worker #include "context.h"
35*61046927SAndroid Build Coastguard Worker #include "enums.h"
36*61046927SAndroid Build Coastguard Worker #include "feedback.h"
37*61046927SAndroid Build Coastguard Worker #include "macros.h"
38*61046927SAndroid Build Coastguard Worker #include "mtypes.h"
39*61046927SAndroid Build Coastguard Worker #include "api_exec_decl.h"
40*61046927SAndroid Build Coastguard Worker #include "bufferobj.h"
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_cb_feedback.h"
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker #define FB_3D		0x01
45*61046927SAndroid Build Coastguard Worker #define FB_4D		0x02
46*61046927SAndroid Build Coastguard Worker #define FB_COLOR	0x04
47*61046927SAndroid Build Coastguard Worker #define FB_TEXTURE	0X08
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_FeedbackBuffer(GLsizei size,GLenum type,GLfloat * buffer)52*61046927SAndroid Build Coastguard Worker _mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer )
53*61046927SAndroid Build Coastguard Worker {
54*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker    if (ctx->RenderMode==GL_FEEDBACK) {
57*61046927SAndroid Build Coastguard Worker       _mesa_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
58*61046927SAndroid Build Coastguard Worker       return;
59*61046927SAndroid Build Coastguard Worker    }
60*61046927SAndroid Build Coastguard Worker    if (size<0) {
61*61046927SAndroid Build Coastguard Worker       _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
62*61046927SAndroid Build Coastguard Worker       return;
63*61046927SAndroid Build Coastguard Worker    }
64*61046927SAndroid Build Coastguard Worker    if (!buffer && size > 0) {
65*61046927SAndroid Build Coastguard Worker       _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
66*61046927SAndroid Build Coastguard Worker       ctx->Feedback.BufferSize = 0;
67*61046927SAndroid Build Coastguard Worker       return;
68*61046927SAndroid Build Coastguard Worker    }
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker    switch (type) {
71*61046927SAndroid Build Coastguard Worker       case GL_2D:
72*61046927SAndroid Build Coastguard Worker 	 ctx->Feedback._Mask = 0;
73*61046927SAndroid Build Coastguard Worker 	 break;
74*61046927SAndroid Build Coastguard Worker       case GL_3D:
75*61046927SAndroid Build Coastguard Worker 	 ctx->Feedback._Mask = FB_3D;
76*61046927SAndroid Build Coastguard Worker 	 break;
77*61046927SAndroid Build Coastguard Worker       case GL_3D_COLOR:
78*61046927SAndroid Build Coastguard Worker 	 ctx->Feedback._Mask = (FB_3D | FB_COLOR);
79*61046927SAndroid Build Coastguard Worker 	 break;
80*61046927SAndroid Build Coastguard Worker       case GL_3D_COLOR_TEXTURE:
81*61046927SAndroid Build Coastguard Worker 	 ctx->Feedback._Mask = (FB_3D | FB_COLOR | FB_TEXTURE);
82*61046927SAndroid Build Coastguard Worker 	 break;
83*61046927SAndroid Build Coastguard Worker       case GL_4D_COLOR_TEXTURE:
84*61046927SAndroid Build Coastguard Worker 	 ctx->Feedback._Mask = (FB_3D | FB_4D | FB_COLOR | FB_TEXTURE);
85*61046927SAndroid Build Coastguard Worker 	 break;
86*61046927SAndroid Build Coastguard Worker       default:
87*61046927SAndroid Build Coastguard Worker          _mesa_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
88*61046927SAndroid Build Coastguard Worker 	 return;
89*61046927SAndroid Build Coastguard Worker    }
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    FLUSH_VERTICES(ctx, _NEW_RENDERMODE, 0); /* Always flush */
92*61046927SAndroid Build Coastguard Worker    ctx->Feedback.Type = type;
93*61046927SAndroid Build Coastguard Worker    ctx->Feedback.BufferSize = size;
94*61046927SAndroid Build Coastguard Worker    ctx->Feedback.Buffer = buffer;
95*61046927SAndroid Build Coastguard Worker    ctx->Feedback.Count = 0;	              /* Because of this. */
96*61046927SAndroid Build Coastguard Worker }
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_PassThrough(GLfloat token)100*61046927SAndroid Build Coastguard Worker _mesa_PassThrough( GLfloat token )
101*61046927SAndroid Build Coastguard Worker {
102*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    if (ctx->RenderMode==GL_FEEDBACK) {
105*61046927SAndroid Build Coastguard Worker       FLUSH_VERTICES(ctx, 0, 0);
106*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
107*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, token );
108*61046927SAndroid Build Coastguard Worker    }
109*61046927SAndroid Build Coastguard Worker }
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker /**
113*61046927SAndroid Build Coastguard Worker  * Put a vertex into the feedback buffer.
114*61046927SAndroid Build Coastguard Worker  */
115*61046927SAndroid Build Coastguard Worker void
_mesa_feedback_vertex(struct gl_context * ctx,const GLfloat win[4],const GLfloat color[4],const GLfloat texcoord[4])116*61046927SAndroid Build Coastguard Worker _mesa_feedback_vertex(struct gl_context *ctx,
117*61046927SAndroid Build Coastguard Worker                       const GLfloat win[4],
118*61046927SAndroid Build Coastguard Worker                       const GLfloat color[4],
119*61046927SAndroid Build Coastguard Worker                       const GLfloat texcoord[4])
120*61046927SAndroid Build Coastguard Worker {
121*61046927SAndroid Build Coastguard Worker    _mesa_feedback_token( ctx, win[0] );
122*61046927SAndroid Build Coastguard Worker    _mesa_feedback_token( ctx, win[1] );
123*61046927SAndroid Build Coastguard Worker    if (ctx->Feedback._Mask & FB_3D) {
124*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, win[2] );
125*61046927SAndroid Build Coastguard Worker    }
126*61046927SAndroid Build Coastguard Worker    if (ctx->Feedback._Mask & FB_4D) {
127*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, win[3] );
128*61046927SAndroid Build Coastguard Worker    }
129*61046927SAndroid Build Coastguard Worker    if (ctx->Feedback._Mask & FB_COLOR) {
130*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, color[0] );
131*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, color[1] );
132*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, color[2] );
133*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, color[3] );
134*61046927SAndroid Build Coastguard Worker    }
135*61046927SAndroid Build Coastguard Worker    if (ctx->Feedback._Mask & FB_TEXTURE) {
136*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, texcoord[0] );
137*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, texcoord[1] );
138*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, texcoord[2] );
139*61046927SAndroid Build Coastguard Worker       _mesa_feedback_token( ctx, texcoord[3] );
140*61046927SAndroid Build Coastguard Worker    }
141*61046927SAndroid Build Coastguard Worker }
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker /**********************************************************************/
145*61046927SAndroid Build Coastguard Worker /** \name Selection */
146*61046927SAndroid Build Coastguard Worker /*@{*/
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker /**
149*61046927SAndroid Build Coastguard Worker  * Establish a buffer for selection mode values.
150*61046927SAndroid Build Coastguard Worker  *
151*61046927SAndroid Build Coastguard Worker  * \param size buffer size.
152*61046927SAndroid Build Coastguard Worker  * \param buffer buffer.
153*61046927SAndroid Build Coastguard Worker  *
154*61046927SAndroid Build Coastguard Worker  * \sa glSelectBuffer().
155*61046927SAndroid Build Coastguard Worker  *
156*61046927SAndroid Build Coastguard Worker  * \note this function can't be put in a display list.
157*61046927SAndroid Build Coastguard Worker  *
158*61046927SAndroid Build Coastguard Worker  * Verifies we're not in selection mode, flushes the vertices and initialize
159*61046927SAndroid Build Coastguard Worker  * the fields in __struct gl_contextRec::Select with the given buffer.
160*61046927SAndroid Build Coastguard Worker  */
161*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_SelectBuffer(GLsizei size,GLuint * buffer)162*61046927SAndroid Build Coastguard Worker _mesa_SelectBuffer( GLsizei size, GLuint *buffer )
163*61046927SAndroid Build Coastguard Worker {
164*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker    if (size < 0) {
167*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "glSelectBuffer(size)");
168*61046927SAndroid Build Coastguard Worker       return;
169*61046927SAndroid Build Coastguard Worker    }
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    if (ctx->RenderMode==GL_SELECT) {
172*61046927SAndroid Build Coastguard Worker       _mesa_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
173*61046927SAndroid Build Coastguard Worker       return;			/* KW: added return */
174*61046927SAndroid Build Coastguard Worker    }
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker    FLUSH_VERTICES(ctx, _NEW_RENDERMODE, 0);
177*61046927SAndroid Build Coastguard Worker    ctx->Select.Buffer = buffer;
178*61046927SAndroid Build Coastguard Worker    ctx->Select.BufferSize = size;
179*61046927SAndroid Build Coastguard Worker    ctx->Select.BufferCount = 0;
180*61046927SAndroid Build Coastguard Worker    ctx->Select.HitFlag = GL_FALSE;
181*61046927SAndroid Build Coastguard Worker    ctx->Select.HitMinZ = 1.0;
182*61046927SAndroid Build Coastguard Worker    ctx->Select.HitMaxZ = 0.0;
183*61046927SAndroid Build Coastguard Worker }
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker /**
187*61046927SAndroid Build Coastguard Worker  * Write a value of a record into the selection buffer.
188*61046927SAndroid Build Coastguard Worker  *
189*61046927SAndroid Build Coastguard Worker  * \param ctx GL context.
190*61046927SAndroid Build Coastguard Worker  * \param value value.
191*61046927SAndroid Build Coastguard Worker  *
192*61046927SAndroid Build Coastguard Worker  * Verifies there is free space in the buffer to write the value and
193*61046927SAndroid Build Coastguard Worker  * increments the pointer.
194*61046927SAndroid Build Coastguard Worker  */
195*61046927SAndroid Build Coastguard Worker static inline void
write_record(struct gl_context * ctx,GLuint value)196*61046927SAndroid Build Coastguard Worker write_record(struct gl_context *ctx, GLuint value)
197*61046927SAndroid Build Coastguard Worker {
198*61046927SAndroid Build Coastguard Worker    if (ctx->Select.BufferCount < ctx->Select.BufferSize) {
199*61046927SAndroid Build Coastguard Worker       ctx->Select.Buffer[ctx->Select.BufferCount] = value;
200*61046927SAndroid Build Coastguard Worker    }
201*61046927SAndroid Build Coastguard Worker    ctx->Select.BufferCount++;
202*61046927SAndroid Build Coastguard Worker }
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker /**
206*61046927SAndroid Build Coastguard Worker  * Update the hit flag and the maximum and minimum depth values.
207*61046927SAndroid Build Coastguard Worker  *
208*61046927SAndroid Build Coastguard Worker  * \param ctx GL context.
209*61046927SAndroid Build Coastguard Worker  * \param z depth.
210*61046927SAndroid Build Coastguard Worker  *
211*61046927SAndroid Build Coastguard Worker  * Sets gl_selection::HitFlag and updates gl_selection::HitMinZ and
212*61046927SAndroid Build Coastguard Worker  * gl_selection::HitMaxZ.
213*61046927SAndroid Build Coastguard Worker  */
214*61046927SAndroid Build Coastguard Worker void
_mesa_update_hitflag(struct gl_context * ctx,GLfloat z)215*61046927SAndroid Build Coastguard Worker _mesa_update_hitflag(struct gl_context *ctx, GLfloat z)
216*61046927SAndroid Build Coastguard Worker {
217*61046927SAndroid Build Coastguard Worker    ctx->Select.HitFlag = GL_TRUE;
218*61046927SAndroid Build Coastguard Worker    if (z < ctx->Select.HitMinZ) {
219*61046927SAndroid Build Coastguard Worker       ctx->Select.HitMinZ = z;
220*61046927SAndroid Build Coastguard Worker    }
221*61046927SAndroid Build Coastguard Worker    if (z > ctx->Select.HitMaxZ) {
222*61046927SAndroid Build Coastguard Worker       ctx->Select.HitMaxZ = z;
223*61046927SAndroid Build Coastguard Worker    }
224*61046927SAndroid Build Coastguard Worker }
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker static void
alloc_select_resource(struct gl_context * ctx)227*61046927SAndroid Build Coastguard Worker alloc_select_resource(struct gl_context *ctx)
228*61046927SAndroid Build Coastguard Worker {
229*61046927SAndroid Build Coastguard Worker    struct gl_selection *s = &ctx->Select;
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    if (!ctx->Const.HardwareAcceleratedSelect)
232*61046927SAndroid Build Coastguard Worker       return;
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker    if (!ctx->Dispatch.HWSelectModeBeginEnd) {
235*61046927SAndroid Build Coastguard Worker       ctx->Dispatch.HWSelectModeBeginEnd = _mesa_alloc_dispatch_table(false);
236*61046927SAndroid Build Coastguard Worker       if (!ctx->Dispatch.HWSelectModeBeginEnd) {
237*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_OUT_OF_MEMORY, "Cannot allocate HWSelectModeBeginEnd");
238*61046927SAndroid Build Coastguard Worker          return;
239*61046927SAndroid Build Coastguard Worker       }
240*61046927SAndroid Build Coastguard Worker       vbo_init_dispatch_hw_select_begin_end(ctx);
241*61046927SAndroid Build Coastguard Worker    }
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker    if (!s->SaveBuffer) {
244*61046927SAndroid Build Coastguard Worker       s->SaveBuffer = malloc(NAME_STACK_BUFFER_SIZE);
245*61046927SAndroid Build Coastguard Worker       if (!s->SaveBuffer) {
246*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_OUT_OF_MEMORY, "Cannot allocate name stack save buffer");
247*61046927SAndroid Build Coastguard Worker          return;
248*61046927SAndroid Build Coastguard Worker       }
249*61046927SAndroid Build Coastguard Worker    }
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker    if (!s->Result) {
252*61046927SAndroid Build Coastguard Worker       s->Result = _mesa_bufferobj_alloc(ctx, -1);
253*61046927SAndroid Build Coastguard Worker       if (!s->Result) {
254*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_OUT_OF_MEMORY, "Cannot allocate select result buffer");
255*61046927SAndroid Build Coastguard Worker          return;
256*61046927SAndroid Build Coastguard Worker       }
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker       GLuint init_result[MAX_NAME_STACK_RESULT_NUM * 3];
259*61046927SAndroid Build Coastguard Worker       for (int i = 0; i < MAX_NAME_STACK_RESULT_NUM; i++) {
260*61046927SAndroid Build Coastguard Worker          init_result[i * 3] = 0;              /* hit */
261*61046927SAndroid Build Coastguard Worker          init_result[i * 3 + 1] = 0xffffffff; /* minz */
262*61046927SAndroid Build Coastguard Worker          init_result[i * 3 + 2] = 0;          /* maxz */
263*61046927SAndroid Build Coastguard Worker       }
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker       bool success = _mesa_bufferobj_data(ctx,
266*61046927SAndroid Build Coastguard Worker                                           GL_SHADER_STORAGE_BUFFER,
267*61046927SAndroid Build Coastguard Worker                                           sizeof(init_result),
268*61046927SAndroid Build Coastguard Worker                                           init_result,
269*61046927SAndroid Build Coastguard Worker                                           GL_STATIC_DRAW, 0,
270*61046927SAndroid Build Coastguard Worker                                           s->Result);
271*61046927SAndroid Build Coastguard Worker       if (!success) {
272*61046927SAndroid Build Coastguard Worker          _mesa_reference_buffer_object(ctx, &s->Result, NULL);
273*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_OUT_OF_MEMORY, "Cannot init result buffer");
274*61046927SAndroid Build Coastguard Worker          return;
275*61046927SAndroid Build Coastguard Worker       }
276*61046927SAndroid Build Coastguard Worker    }
277*61046927SAndroid Build Coastguard Worker }
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker static bool
save_used_name_stack(struct gl_context * ctx)280*61046927SAndroid Build Coastguard Worker save_used_name_stack(struct gl_context *ctx)
281*61046927SAndroid Build Coastguard Worker {
282*61046927SAndroid Build Coastguard Worker    struct gl_selection *s = &ctx->Select;
283*61046927SAndroid Build Coastguard Worker 
284*61046927SAndroid Build Coastguard Worker    if (!ctx->Const.HardwareAcceleratedSelect)
285*61046927SAndroid Build Coastguard Worker       return false;
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker    /* We have two kinds of name stack user:
288*61046927SAndroid Build Coastguard Worker     *   1. glRasterPos (CPU based) will set HitFlag
289*61046927SAndroid Build Coastguard Worker     *   2. draw call for GPU will set ResultUsed
290*61046927SAndroid Build Coastguard Worker     */
291*61046927SAndroid Build Coastguard Worker    if (!s->ResultUsed && !s->HitFlag)
292*61046927SAndroid Build Coastguard Worker       return false;
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker    void *save = (char *)s->SaveBuffer + s->SaveBufferTail;
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker    /* save meta data */
297*61046927SAndroid Build Coastguard Worker    uint8_t *metadata = save;
298*61046927SAndroid Build Coastguard Worker    metadata[0] = s->HitFlag;
299*61046927SAndroid Build Coastguard Worker    metadata[1] = s->ResultUsed;
300*61046927SAndroid Build Coastguard Worker    metadata[2] = s->NameStackDepth;
301*61046927SAndroid Build Coastguard Worker    metadata[3] = 0;
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker    /* save hit data */
304*61046927SAndroid Build Coastguard Worker    int index = 1;
305*61046927SAndroid Build Coastguard Worker    if (s->HitFlag) {
306*61046927SAndroid Build Coastguard Worker       float *hit = save;
307*61046927SAndroid Build Coastguard Worker       hit[index++] = s->HitMinZ;
308*61046927SAndroid Build Coastguard Worker       hit[index++] = s->HitMaxZ;
309*61046927SAndroid Build Coastguard Worker    }
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker    /* save name stack */
312*61046927SAndroid Build Coastguard Worker    memcpy((uint32_t *)save + index, s->NameStack, s->NameStackDepth * sizeof(GLuint));
313*61046927SAndroid Build Coastguard Worker    index += s->NameStackDepth;
314*61046927SAndroid Build Coastguard Worker 
315*61046927SAndroid Build Coastguard Worker    s->SaveBufferTail += index * sizeof(GLuint);
316*61046927SAndroid Build Coastguard Worker    s->SavedStackNum++;
317*61046927SAndroid Build Coastguard Worker 
318*61046927SAndroid Build Coastguard Worker    /* if current slot has been used, store result to next slot in result buffer */
319*61046927SAndroid Build Coastguard Worker    if (s->ResultUsed)
320*61046927SAndroid Build Coastguard Worker       s->ResultOffset += 3 * sizeof(GLuint);
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker    /* reset fields */
323*61046927SAndroid Build Coastguard Worker    s->HitFlag = GL_FALSE;
324*61046927SAndroid Build Coastguard Worker    s->HitMinZ = 1.0;
325*61046927SAndroid Build Coastguard Worker    s->HitMaxZ = 0;
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker    s->ResultUsed = GL_FALSE;
328*61046927SAndroid Build Coastguard Worker 
329*61046927SAndroid Build Coastguard Worker    /* return true if we have no enough space for the next name stack data */
330*61046927SAndroid Build Coastguard Worker    return s->ResultOffset >= MAX_NAME_STACK_RESULT_NUM * 3 * sizeof(GLuint) ||
331*61046927SAndroid Build Coastguard Worker       s->SaveBufferTail >= NAME_STACK_BUFFER_SIZE - (MAX_NAME_STACK_DEPTH + 3) * sizeof(GLuint);
332*61046927SAndroid Build Coastguard Worker }
333*61046927SAndroid Build Coastguard Worker 
334*61046927SAndroid Build Coastguard Worker static void
update_hit_record(struct gl_context * ctx)335*61046927SAndroid Build Coastguard Worker update_hit_record(struct gl_context *ctx)
336*61046927SAndroid Build Coastguard Worker {
337*61046927SAndroid Build Coastguard Worker    struct gl_selection *s = &ctx->Select;
338*61046927SAndroid Build Coastguard Worker 
339*61046927SAndroid Build Coastguard Worker    if (ctx->Const.HardwareAcceleratedSelect) {
340*61046927SAndroid Build Coastguard Worker       if (!s->SavedStackNum)
341*61046927SAndroid Build Coastguard Worker          return;
342*61046927SAndroid Build Coastguard Worker 
343*61046927SAndroid Build Coastguard Worker       unsigned size = s->ResultOffset;
344*61046927SAndroid Build Coastguard Worker       GLuint *result = size ? alloca(size) : NULL;
345*61046927SAndroid Build Coastguard Worker       _mesa_bufferobj_get_subdata(ctx, 0, size, result, s->Result);
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker       unsigned index = 0;
348*61046927SAndroid Build Coastguard Worker       unsigned *save = s->SaveBuffer;
349*61046927SAndroid Build Coastguard Worker       for (int i = 0; i < s->SavedStackNum; i++) {
350*61046927SAndroid Build Coastguard Worker          uint8_t *metadata = (uint8_t *)(save++);
351*61046927SAndroid Build Coastguard Worker 
352*61046927SAndroid Build Coastguard Worker          unsigned zmin, zmax;
353*61046927SAndroid Build Coastguard Worker          bool cpu_hit = !!metadata[0];
354*61046927SAndroid Build Coastguard Worker          if (cpu_hit) {
355*61046927SAndroid Build Coastguard Worker             /* map [0, 1] to [0, UINT_MAX]*/
356*61046927SAndroid Build Coastguard Worker             zmin = (unsigned) ((float)(~0u) * *(float *)(save++));
357*61046927SAndroid Build Coastguard Worker             zmax = (unsigned) ((float)(~0u) * *(float *)(save++));
358*61046927SAndroid Build Coastguard Worker          } else {
359*61046927SAndroid Build Coastguard Worker             zmin = ~0u;
360*61046927SAndroid Build Coastguard Worker             zmax = 0;
361*61046927SAndroid Build Coastguard Worker          }
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker          bool gpu_hit = false;
364*61046927SAndroid Build Coastguard Worker          if (metadata[1]) {
365*61046927SAndroid Build Coastguard Worker             gpu_hit = !!result[index];
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker             if (gpu_hit) {
368*61046927SAndroid Build Coastguard Worker                zmin = MIN2(zmin, result[index + 1]);
369*61046927SAndroid Build Coastguard Worker                zmax = MAX2(zmax, result[index + 2]);
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker                /* reset data */
372*61046927SAndroid Build Coastguard Worker                result[index]     = 0;          /* hit */
373*61046927SAndroid Build Coastguard Worker                result[index + 1] = 0xffffffff; /* minz */
374*61046927SAndroid Build Coastguard Worker                result[index + 2] = 0;          /* maxz */
375*61046927SAndroid Build Coastguard Worker             }
376*61046927SAndroid Build Coastguard Worker             index += 3;
377*61046927SAndroid Build Coastguard Worker          }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker          int depth = metadata[2];
380*61046927SAndroid Build Coastguard Worker          if (cpu_hit || gpu_hit) {
381*61046927SAndroid Build Coastguard Worker             /* hit */
382*61046927SAndroid Build Coastguard Worker             write_record(ctx, depth);
383*61046927SAndroid Build Coastguard Worker             write_record(ctx, zmin);
384*61046927SAndroid Build Coastguard Worker             write_record(ctx, zmax);
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker             for (int j = 0; j < depth; j++)
387*61046927SAndroid Build Coastguard Worker                write_record(ctx, save[j]);
388*61046927SAndroid Build Coastguard Worker             s->Hits++;
389*61046927SAndroid Build Coastguard Worker          }
390*61046927SAndroid Build Coastguard Worker          save += depth;
391*61046927SAndroid Build Coastguard Worker       }
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker       /* reset result buffer */
394*61046927SAndroid Build Coastguard Worker       _mesa_bufferobj_subdata(ctx, 0, size, result, s->Result);
395*61046927SAndroid Build Coastguard Worker 
396*61046927SAndroid Build Coastguard Worker       s->SaveBufferTail = 0;
397*61046927SAndroid Build Coastguard Worker       s->SavedStackNum = 0;
398*61046927SAndroid Build Coastguard Worker       s->ResultOffset = 0;
399*61046927SAndroid Build Coastguard Worker    } else {
400*61046927SAndroid Build Coastguard Worker       if (!s->HitFlag)
401*61046927SAndroid Build Coastguard Worker          return;
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker       /* HitMinZ and HitMaxZ are in [0,1].  Multiply these values by */
404*61046927SAndroid Build Coastguard Worker       /* 2^32-1 and round to nearest unsigned integer. */
405*61046927SAndroid Build Coastguard Worker       GLuint zscale = (~0u);
406*61046927SAndroid Build Coastguard Worker       GLuint zmin = (GLuint) ((GLfloat) zscale * s->HitMinZ);
407*61046927SAndroid Build Coastguard Worker       GLuint zmax = (GLuint) ((GLfloat) zscale * s->HitMaxZ);
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker       write_record(ctx, s->NameStackDepth);
410*61046927SAndroid Build Coastguard Worker       write_record(ctx, zmin);
411*61046927SAndroid Build Coastguard Worker       write_record(ctx, zmax);
412*61046927SAndroid Build Coastguard Worker       for (int i = 0; i < s->NameStackDepth; i++)
413*61046927SAndroid Build Coastguard Worker          write_record(ctx, s->NameStack[i]);
414*61046927SAndroid Build Coastguard Worker 
415*61046927SAndroid Build Coastguard Worker       s->HitFlag = GL_FALSE;
416*61046927SAndroid Build Coastguard Worker       s->HitMinZ = 1.0;
417*61046927SAndroid Build Coastguard Worker       s->HitMaxZ = -1.0;
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker       s->Hits++;
420*61046927SAndroid Build Coastguard Worker    }
421*61046927SAndroid Build Coastguard Worker }
422*61046927SAndroid Build Coastguard Worker 
423*61046927SAndroid Build Coastguard Worker static void
reset_name_stack_to_empty(struct gl_context * ctx)424*61046927SAndroid Build Coastguard Worker reset_name_stack_to_empty(struct gl_context *ctx)
425*61046927SAndroid Build Coastguard Worker {
426*61046927SAndroid Build Coastguard Worker    struct gl_selection *s = &ctx->Select;
427*61046927SAndroid Build Coastguard Worker 
428*61046927SAndroid Build Coastguard Worker    s->NameStackDepth = 0;
429*61046927SAndroid Build Coastguard Worker    s->HitFlag = GL_FALSE;
430*61046927SAndroid Build Coastguard Worker    s->HitMinZ = 1.0;
431*61046927SAndroid Build Coastguard Worker    s->HitMaxZ = 0.0;
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker    if (ctx->Const.HardwareAcceleratedSelect) {
434*61046927SAndroid Build Coastguard Worker       s->SaveBufferTail = 0;
435*61046927SAndroid Build Coastguard Worker       s->SavedStackNum = 0;
436*61046927SAndroid Build Coastguard Worker       s->ResultUsed = GL_FALSE;
437*61046927SAndroid Build Coastguard Worker       s->ResultOffset = 0;
438*61046927SAndroid Build Coastguard Worker    }
439*61046927SAndroid Build Coastguard Worker }
440*61046927SAndroid Build Coastguard Worker 
441*61046927SAndroid Build Coastguard Worker /**
442*61046927SAndroid Build Coastguard Worker  * Initialize the name stack.
443*61046927SAndroid Build Coastguard Worker  */
444*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_InitNames(void)445*61046927SAndroid Build Coastguard Worker _mesa_InitNames( void )
446*61046927SAndroid Build Coastguard Worker {
447*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker    /* Calls to glInitNames while the render mode is not GL_SELECT are ignored. */
450*61046927SAndroid Build Coastguard Worker    if (ctx->RenderMode != GL_SELECT)
451*61046927SAndroid Build Coastguard Worker       return;
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker    FLUSH_VERTICES(ctx, 0, 0);
454*61046927SAndroid Build Coastguard Worker 
455*61046927SAndroid Build Coastguard Worker    save_used_name_stack(ctx);
456*61046927SAndroid Build Coastguard Worker    update_hit_record(ctx);
457*61046927SAndroid Build Coastguard Worker 
458*61046927SAndroid Build Coastguard Worker    reset_name_stack_to_empty(ctx);
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker    ctx->NewState |= _NEW_RENDERMODE;
461*61046927SAndroid Build Coastguard Worker }
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker 
464*61046927SAndroid Build Coastguard Worker /**
465*61046927SAndroid Build Coastguard Worker  * Load the top-most name of the name stack.
466*61046927SAndroid Build Coastguard Worker  *
467*61046927SAndroid Build Coastguard Worker  * \param name name.
468*61046927SAndroid Build Coastguard Worker  */
469*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_LoadName(GLuint name)470*61046927SAndroid Build Coastguard Worker _mesa_LoadName( GLuint name )
471*61046927SAndroid Build Coastguard Worker {
472*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
473*61046927SAndroid Build Coastguard Worker 
474*61046927SAndroid Build Coastguard Worker    if (ctx->RenderMode != GL_SELECT) {
475*61046927SAndroid Build Coastguard Worker       return;
476*61046927SAndroid Build Coastguard Worker    }
477*61046927SAndroid Build Coastguard Worker    if (ctx->Select.NameStackDepth == 0) {
478*61046927SAndroid Build Coastguard Worker       _mesa_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
479*61046927SAndroid Build Coastguard Worker       return;
480*61046927SAndroid Build Coastguard Worker    }
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker    if (!ctx->Const.HardwareAcceleratedSelect || save_used_name_stack(ctx)) {
483*61046927SAndroid Build Coastguard Worker       FLUSH_VERTICES(ctx, 0, 0);
484*61046927SAndroid Build Coastguard Worker       update_hit_record(ctx);
485*61046927SAndroid Build Coastguard Worker    }
486*61046927SAndroid Build Coastguard Worker 
487*61046927SAndroid Build Coastguard Worker    ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name;
488*61046927SAndroid Build Coastguard Worker    ctx->NewState |= _NEW_RENDERMODE;
489*61046927SAndroid Build Coastguard Worker }
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker 
492*61046927SAndroid Build Coastguard Worker /**
493*61046927SAndroid Build Coastguard Worker  * Push a name into the name stack.
494*61046927SAndroid Build Coastguard Worker  *
495*61046927SAndroid Build Coastguard Worker  * \param name name.
496*61046927SAndroid Build Coastguard Worker  */
497*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_PushName(GLuint name)498*61046927SAndroid Build Coastguard Worker _mesa_PushName( GLuint name )
499*61046927SAndroid Build Coastguard Worker {
500*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
501*61046927SAndroid Build Coastguard Worker 
502*61046927SAndroid Build Coastguard Worker    if (ctx->RenderMode != GL_SELECT) {
503*61046927SAndroid Build Coastguard Worker       return;
504*61046927SAndroid Build Coastguard Worker    }
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker    if (ctx->Select.NameStackDepth >= MAX_NAME_STACK_DEPTH) {
507*61046927SAndroid Build Coastguard Worker       _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
508*61046927SAndroid Build Coastguard Worker       return;
509*61046927SAndroid Build Coastguard Worker    }
510*61046927SAndroid Build Coastguard Worker 
511*61046927SAndroid Build Coastguard Worker    if (!ctx->Const.HardwareAcceleratedSelect || save_used_name_stack(ctx)) {
512*61046927SAndroid Build Coastguard Worker       FLUSH_VERTICES(ctx, 0, 0);
513*61046927SAndroid Build Coastguard Worker       update_hit_record(ctx);
514*61046927SAndroid Build Coastguard Worker    }
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker    ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
517*61046927SAndroid Build Coastguard Worker    ctx->NewState |= _NEW_RENDERMODE;
518*61046927SAndroid Build Coastguard Worker }
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker /**
522*61046927SAndroid Build Coastguard Worker  * Pop a name into the name stack.
523*61046927SAndroid Build Coastguard Worker  */
524*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_PopName(void)525*61046927SAndroid Build Coastguard Worker _mesa_PopName( void )
526*61046927SAndroid Build Coastguard Worker {
527*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker    if (ctx->RenderMode != GL_SELECT) {
530*61046927SAndroid Build Coastguard Worker       return;
531*61046927SAndroid Build Coastguard Worker    }
532*61046927SAndroid Build Coastguard Worker 
533*61046927SAndroid Build Coastguard Worker    if (ctx->Select.NameStackDepth == 0) {
534*61046927SAndroid Build Coastguard Worker       _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
535*61046927SAndroid Build Coastguard Worker       return;
536*61046927SAndroid Build Coastguard Worker    }
537*61046927SAndroid Build Coastguard Worker 
538*61046927SAndroid Build Coastguard Worker    if (!ctx->Const.HardwareAcceleratedSelect || save_used_name_stack(ctx)) {
539*61046927SAndroid Build Coastguard Worker       FLUSH_VERTICES(ctx, 0, 0);
540*61046927SAndroid Build Coastguard Worker       update_hit_record(ctx);
541*61046927SAndroid Build Coastguard Worker    }
542*61046927SAndroid Build Coastguard Worker 
543*61046927SAndroid Build Coastguard Worker    ctx->Select.NameStackDepth--;
544*61046927SAndroid Build Coastguard Worker    ctx->NewState |= _NEW_RENDERMODE;
545*61046927SAndroid Build Coastguard Worker }
546*61046927SAndroid Build Coastguard Worker 
547*61046927SAndroid Build Coastguard Worker /*@}*/
548*61046927SAndroid Build Coastguard Worker 
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker /**********************************************************************/
551*61046927SAndroid Build Coastguard Worker /** \name Render Mode */
552*61046927SAndroid Build Coastguard Worker /*@{*/
553*61046927SAndroid Build Coastguard Worker 
554*61046927SAndroid Build Coastguard Worker /**
555*61046927SAndroid Build Coastguard Worker  * Set rasterization mode.
556*61046927SAndroid Build Coastguard Worker  *
557*61046927SAndroid Build Coastguard Worker  * \param mode rasterization mode.
558*61046927SAndroid Build Coastguard Worker  *
559*61046927SAndroid Build Coastguard Worker  * \note this function can't be put in a display list.
560*61046927SAndroid Build Coastguard Worker  *
561*61046927SAndroid Build Coastguard Worker  * \sa glRenderMode().
562*61046927SAndroid Build Coastguard Worker  *
563*61046927SAndroid Build Coastguard Worker  * Flushes the vertices and do the necessary cleanup according to the previous
564*61046927SAndroid Build Coastguard Worker  * rasterization mode, such as writing the hit record or resent the select
565*61046927SAndroid Build Coastguard Worker  * buffer index when exiting the select mode. Updates
566*61046927SAndroid Build Coastguard Worker  * __struct gl_contextRec::RenderMode and notifies the driver via the
567*61046927SAndroid Build Coastguard Worker  * dd_function_table::RenderMode callback.
568*61046927SAndroid Build Coastguard Worker  */
569*61046927SAndroid Build Coastguard Worker GLint GLAPIENTRY
_mesa_RenderMode(GLenum mode)570*61046927SAndroid Build Coastguard Worker _mesa_RenderMode( GLenum mode )
571*61046927SAndroid Build Coastguard Worker {
572*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
573*61046927SAndroid Build Coastguard Worker    GLint result;
574*61046927SAndroid Build Coastguard Worker    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
575*61046927SAndroid Build Coastguard Worker 
576*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
577*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glRenderMode %s\n", _mesa_enum_to_string(mode));
578*61046927SAndroid Build Coastguard Worker 
579*61046927SAndroid Build Coastguard Worker    FLUSH_VERTICES(ctx, _NEW_RENDERMODE | _NEW_FF_VERT_PROGRAM |
580*61046927SAndroid Build Coastguard Worker                   _NEW_FF_FRAG_PROGRAM, 0);
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker    switch (ctx->RenderMode) {
583*61046927SAndroid Build Coastguard Worker       case GL_RENDER:
584*61046927SAndroid Build Coastguard Worker 	 result = 0;
585*61046927SAndroid Build Coastguard Worker 	 break;
586*61046927SAndroid Build Coastguard Worker       case GL_SELECT:
587*61046927SAndroid Build Coastguard Worker 	 save_used_name_stack(ctx);
588*61046927SAndroid Build Coastguard Worker 	 update_hit_record(ctx);
589*61046927SAndroid Build Coastguard Worker 
590*61046927SAndroid Build Coastguard Worker 	 if (ctx->Select.BufferCount > ctx->Select.BufferSize) {
591*61046927SAndroid Build Coastguard Worker 	    /* overflow */
592*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
593*61046927SAndroid Build Coastguard Worker             _mesa_warning(ctx, "Feedback buffer overflow");
594*61046927SAndroid Build Coastguard Worker #endif
595*61046927SAndroid Build Coastguard Worker 	    result = -1;
596*61046927SAndroid Build Coastguard Worker 	 }
597*61046927SAndroid Build Coastguard Worker 	 else {
598*61046927SAndroid Build Coastguard Worker 	    result = ctx->Select.Hits;
599*61046927SAndroid Build Coastguard Worker 	 }
600*61046927SAndroid Build Coastguard Worker 	 ctx->Select.BufferCount = 0;
601*61046927SAndroid Build Coastguard Worker 	 ctx->Select.Hits = 0;
602*61046927SAndroid Build Coastguard Worker 	 /* name stack should be in empty state after exiting GL_SELECT mode */
603*61046927SAndroid Build Coastguard Worker 	 reset_name_stack_to_empty(ctx);
604*61046927SAndroid Build Coastguard Worker 	 break;
605*61046927SAndroid Build Coastguard Worker       case GL_FEEDBACK:
606*61046927SAndroid Build Coastguard Worker 	 if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
607*61046927SAndroid Build Coastguard Worker 	    /* overflow */
608*61046927SAndroid Build Coastguard Worker 	    result = -1;
609*61046927SAndroid Build Coastguard Worker 	 }
610*61046927SAndroid Build Coastguard Worker 	 else {
611*61046927SAndroid Build Coastguard Worker 	    result = ctx->Feedback.Count;
612*61046927SAndroid Build Coastguard Worker 	 }
613*61046927SAndroid Build Coastguard Worker 	 ctx->Feedback.Count = 0;
614*61046927SAndroid Build Coastguard Worker 	 break;
615*61046927SAndroid Build Coastguard Worker       default:
616*61046927SAndroid Build Coastguard Worker 	 _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
617*61046927SAndroid Build Coastguard Worker 	 return 0;
618*61046927SAndroid Build Coastguard Worker    }
619*61046927SAndroid Build Coastguard Worker 
620*61046927SAndroid Build Coastguard Worker    switch (mode) {
621*61046927SAndroid Build Coastguard Worker       case GL_RENDER:
622*61046927SAndroid Build Coastguard Worker          break;
623*61046927SAndroid Build Coastguard Worker       case GL_SELECT:
624*61046927SAndroid Build Coastguard Worker 	 if (ctx->Select.BufferSize==0) {
625*61046927SAndroid Build Coastguard Worker 	    /* haven't called glSelectBuffer yet */
626*61046927SAndroid Build Coastguard Worker 	    _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
627*61046927SAndroid Build Coastguard Worker 	 }
628*61046927SAndroid Build Coastguard Worker 	 alloc_select_resource(ctx);
629*61046927SAndroid Build Coastguard Worker 	 break;
630*61046927SAndroid Build Coastguard Worker       case GL_FEEDBACK:
631*61046927SAndroid Build Coastguard Worker 	 if (ctx->Feedback.BufferSize==0) {
632*61046927SAndroid Build Coastguard Worker 	    /* haven't called glFeedbackBuffer yet */
633*61046927SAndroid Build Coastguard Worker 	    _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
634*61046927SAndroid Build Coastguard Worker 	 }
635*61046927SAndroid Build Coastguard Worker 	 break;
636*61046927SAndroid Build Coastguard Worker       default:
637*61046927SAndroid Build Coastguard Worker 	 _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
638*61046927SAndroid Build Coastguard Worker 	 return 0;
639*61046927SAndroid Build Coastguard Worker    }
640*61046927SAndroid Build Coastguard Worker 
641*61046927SAndroid Build Coastguard Worker    st_RenderMode( ctx, mode );
642*61046927SAndroid Build Coastguard Worker 
643*61046927SAndroid Build Coastguard Worker    /* finally update render mode to new one */
644*61046927SAndroid Build Coastguard Worker    ctx->RenderMode = mode;
645*61046927SAndroid Build Coastguard Worker 
646*61046927SAndroid Build Coastguard Worker    return result;
647*61046927SAndroid Build Coastguard Worker }
648*61046927SAndroid Build Coastguard Worker 
649*61046927SAndroid Build Coastguard Worker /*@}*/
650*61046927SAndroid Build Coastguard Worker 
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker /**********************************************************************/
653*61046927SAndroid Build Coastguard Worker /** \name Initialization */
654*61046927SAndroid Build Coastguard Worker /*@{*/
655*61046927SAndroid Build Coastguard Worker 
656*61046927SAndroid Build Coastguard Worker /**
657*61046927SAndroid Build Coastguard Worker  * Initialize context feedback data.
658*61046927SAndroid Build Coastguard Worker  */
_mesa_init_feedback(struct gl_context * ctx)659*61046927SAndroid Build Coastguard Worker void _mesa_init_feedback( struct gl_context * ctx )
660*61046927SAndroid Build Coastguard Worker {
661*61046927SAndroid Build Coastguard Worker    /* Feedback */
662*61046927SAndroid Build Coastguard Worker    ctx->Feedback.Type = GL_2D;   /* TODO: verify */
663*61046927SAndroid Build Coastguard Worker    ctx->Feedback.Buffer = NULL;
664*61046927SAndroid Build Coastguard Worker    ctx->Feedback.BufferSize = 0;
665*61046927SAndroid Build Coastguard Worker    ctx->Feedback.Count = 0;
666*61046927SAndroid Build Coastguard Worker 
667*61046927SAndroid Build Coastguard Worker    /* Selection/picking */
668*61046927SAndroid Build Coastguard Worker    ctx->Select.Buffer = NULL;
669*61046927SAndroid Build Coastguard Worker    ctx->Select.BufferSize = 0;
670*61046927SAndroid Build Coastguard Worker    ctx->Select.BufferCount = 0;
671*61046927SAndroid Build Coastguard Worker    ctx->Select.Hits = 0;
672*61046927SAndroid Build Coastguard Worker    ctx->Select.NameStackDepth = 0;
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker    /* Miscellaneous */
675*61046927SAndroid Build Coastguard Worker    ctx->RenderMode = GL_RENDER;
676*61046927SAndroid Build Coastguard Worker }
677*61046927SAndroid Build Coastguard Worker 
_mesa_free_feedback(struct gl_context * ctx)678*61046927SAndroid Build Coastguard Worker void _mesa_free_feedback(struct gl_context * ctx)
679*61046927SAndroid Build Coastguard Worker {
680*61046927SAndroid Build Coastguard Worker    struct gl_selection *s = &ctx->Select;
681*61046927SAndroid Build Coastguard Worker 
682*61046927SAndroid Build Coastguard Worker    free(s->SaveBuffer);
683*61046927SAndroid Build Coastguard Worker    _mesa_reference_buffer_object(ctx, &s->Result, NULL);
684*61046927SAndroid Build Coastguard Worker }
685*61046927SAndroid Build Coastguard Worker 
686*61046927SAndroid Build Coastguard Worker /*@}*/
687