1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/** 29bf215546Sopenharmony_ci * GL_SELECT and GL_FEEDBACK render modes. 30bf215546Sopenharmony_ci * Basically, we use a private instance of the 'draw' module for doing 31bf215546Sopenharmony_ci * selection/feedback. It would be nice to use the transform_feedback 32bf215546Sopenharmony_ci * hardware feature, but it's defined as happening pre-clip and we want 33bf215546Sopenharmony_ci * post-clipped primitives. Also, there's concerns about the efficiency 34bf215546Sopenharmony_ci * of using the hardware for this anyway. 35bf215546Sopenharmony_ci * 36bf215546Sopenharmony_ci * Authors: 37bf215546Sopenharmony_ci * Brian Paul 38bf215546Sopenharmony_ci */ 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "main/context.h" 42bf215546Sopenharmony_ci#include "main/feedback.h" 43bf215546Sopenharmony_ci#include "main/framebuffer.h" 44bf215546Sopenharmony_ci#include "main/varray.h" 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci#include "util/u_memory.h" 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci#include "vbo/vbo.h" 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci#include "st_context.h" 51bf215546Sopenharmony_ci#include "st_draw.h" 52bf215546Sopenharmony_ci#include "st_cb_feedback.h" 53bf215546Sopenharmony_ci#include "st_program.h" 54bf215546Sopenharmony_ci#include "st_util.h" 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci#include "pipe/p_context.h" 57bf215546Sopenharmony_ci#include "pipe/p_defines.h" 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci#include "draw/draw_context.h" 60bf215546Sopenharmony_ci#include "draw/draw_pipe.h" 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci/** 64bf215546Sopenharmony_ci * This is actually used for both feedback and selection. 65bf215546Sopenharmony_ci */ 66bf215546Sopenharmony_cistruct feedback_stage 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci struct draw_stage stage; /**< Base class */ 69bf215546Sopenharmony_ci struct gl_context *ctx; /**< Rendering context */ 70bf215546Sopenharmony_ci GLboolean reset_stipple_counter; 71bf215546Sopenharmony_ci}; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci/********************************************************************** 75bf215546Sopenharmony_ci * GL Feedback functions 76bf215546Sopenharmony_ci **********************************************************************/ 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_cistatic inline struct feedback_stage * 79bf215546Sopenharmony_cifeedback_stage( struct draw_stage *stage ) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci return (struct feedback_stage *)stage; 82bf215546Sopenharmony_ci} 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_cistatic void 86bf215546Sopenharmony_cifeedback_vertex(struct gl_context *ctx, const struct draw_context *draw, 87bf215546Sopenharmony_ci const struct vertex_header *v) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci const struct st_context *st = st_context(ctx); 90bf215546Sopenharmony_ci struct gl_vertex_program *stvp = (struct gl_vertex_program *)st->vp; 91bf215546Sopenharmony_ci GLfloat win[4]; 92bf215546Sopenharmony_ci const GLfloat *color, *texcoord; 93bf215546Sopenharmony_ci ubyte slot; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci win[0] = v->data[0][0]; 96bf215546Sopenharmony_ci if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) 97bf215546Sopenharmony_ci win[1] = ctx->DrawBuffer->Height - v->data[0][1]; 98bf215546Sopenharmony_ci else 99bf215546Sopenharmony_ci win[1] = v->data[0][1]; 100bf215546Sopenharmony_ci win[2] = v->data[0][2]; 101bf215546Sopenharmony_ci win[3] = 1.0F / v->data[0][3]; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci /* XXX 104bf215546Sopenharmony_ci * When we compute vertex layout, save info about position of the 105bf215546Sopenharmony_ci * color and texcoord attribs to use here. 106bf215546Sopenharmony_ci */ 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci slot = stvp->result_to_output[VARYING_SLOT_COL0]; 109bf215546Sopenharmony_ci if (slot != 0xff) 110bf215546Sopenharmony_ci color = v->data[slot]; 111bf215546Sopenharmony_ci else 112bf215546Sopenharmony_ci color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci slot = stvp->result_to_output[VARYING_SLOT_TEX0]; 115bf215546Sopenharmony_ci if (slot != 0xff) 116bf215546Sopenharmony_ci texcoord = v->data[slot]; 117bf215546Sopenharmony_ci else 118bf215546Sopenharmony_ci texcoord = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci _mesa_feedback_vertex(ctx, win, color, texcoord); 121bf215546Sopenharmony_ci} 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_cistatic void 125bf215546Sopenharmony_cifeedback_tri( struct draw_stage *stage, struct prim_header *prim ) 126bf215546Sopenharmony_ci{ 127bf215546Sopenharmony_ci struct feedback_stage *fs = feedback_stage(stage); 128bf215546Sopenharmony_ci struct draw_context *draw = stage->draw; 129bf215546Sopenharmony_ci _mesa_feedback_token(fs->ctx, (GLfloat) GL_POLYGON_TOKEN); 130bf215546Sopenharmony_ci _mesa_feedback_token(fs->ctx, (GLfloat) 3); /* three vertices */ 131bf215546Sopenharmony_ci feedback_vertex(fs->ctx, draw, prim->v[0]); 132bf215546Sopenharmony_ci feedback_vertex(fs->ctx, draw, prim->v[1]); 133bf215546Sopenharmony_ci feedback_vertex(fs->ctx, draw, prim->v[2]); 134bf215546Sopenharmony_ci} 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_cistatic void 138bf215546Sopenharmony_cifeedback_line( struct draw_stage *stage, struct prim_header *prim ) 139bf215546Sopenharmony_ci{ 140bf215546Sopenharmony_ci struct feedback_stage *fs = feedback_stage(stage); 141bf215546Sopenharmony_ci struct draw_context *draw = stage->draw; 142bf215546Sopenharmony_ci if (fs->reset_stipple_counter) { 143bf215546Sopenharmony_ci _mesa_feedback_token(fs->ctx, (GLfloat) GL_LINE_RESET_TOKEN); 144bf215546Sopenharmony_ci fs->reset_stipple_counter = GL_FALSE; 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci else { 147bf215546Sopenharmony_ci _mesa_feedback_token(fs->ctx, (GLfloat) GL_LINE_TOKEN); 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci feedback_vertex(fs->ctx, draw, prim->v[0]); 150bf215546Sopenharmony_ci feedback_vertex(fs->ctx, draw, prim->v[1]); 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_cistatic void 155bf215546Sopenharmony_cifeedback_point( struct draw_stage *stage, struct prim_header *prim ) 156bf215546Sopenharmony_ci{ 157bf215546Sopenharmony_ci struct feedback_stage *fs = feedback_stage(stage); 158bf215546Sopenharmony_ci struct draw_context *draw = stage->draw; 159bf215546Sopenharmony_ci _mesa_feedback_token(fs->ctx, (GLfloat) GL_POINT_TOKEN); 160bf215546Sopenharmony_ci feedback_vertex(fs->ctx, draw, prim->v[0]); 161bf215546Sopenharmony_ci} 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_cistatic void 165bf215546Sopenharmony_cifeedback_flush( struct draw_stage *stage, unsigned flags ) 166bf215546Sopenharmony_ci{ 167bf215546Sopenharmony_ci /* no-op */ 168bf215546Sopenharmony_ci} 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_cistatic void 172bf215546Sopenharmony_cifeedback_reset_stipple_counter( struct draw_stage *stage ) 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci struct feedback_stage *fs = feedback_stage(stage); 175bf215546Sopenharmony_ci fs->reset_stipple_counter = GL_TRUE; 176bf215546Sopenharmony_ci} 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_cistatic void 180bf215546Sopenharmony_cifeedback_destroy( struct draw_stage *stage ) 181bf215546Sopenharmony_ci{ 182bf215546Sopenharmony_ci FREE(stage); 183bf215546Sopenharmony_ci} 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci/** 186bf215546Sopenharmony_ci * Create GL feedback drawing stage. 187bf215546Sopenharmony_ci */ 188bf215546Sopenharmony_cistatic struct draw_stage * 189bf215546Sopenharmony_cidraw_glfeedback_stage(struct gl_context *ctx, struct draw_context *draw) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci struct feedback_stage *fs = CALLOC_STRUCT(feedback_stage); 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci fs->stage.draw = draw; 194bf215546Sopenharmony_ci fs->stage.next = NULL; 195bf215546Sopenharmony_ci fs->stage.point = feedback_point; 196bf215546Sopenharmony_ci fs->stage.line = feedback_line; 197bf215546Sopenharmony_ci fs->stage.tri = feedback_tri; 198bf215546Sopenharmony_ci fs->stage.flush = feedback_flush; 199bf215546Sopenharmony_ci fs->stage.reset_stipple_counter = feedback_reset_stipple_counter; 200bf215546Sopenharmony_ci fs->stage.destroy = feedback_destroy; 201bf215546Sopenharmony_ci fs->ctx = ctx; 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci return &fs->stage; 204bf215546Sopenharmony_ci} 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci/********************************************************************** 209bf215546Sopenharmony_ci * GL Selection functions 210bf215546Sopenharmony_ci **********************************************************************/ 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_cistatic void 213bf215546Sopenharmony_ciselect_tri( struct draw_stage *stage, struct prim_header *prim ) 214bf215546Sopenharmony_ci{ 215bf215546Sopenharmony_ci struct feedback_stage *fs = feedback_stage(stage); 216bf215546Sopenharmony_ci _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] ); 217bf215546Sopenharmony_ci _mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] ); 218bf215546Sopenharmony_ci _mesa_update_hitflag( fs->ctx, prim->v[2]->data[0][2] ); 219bf215546Sopenharmony_ci} 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_cistatic void 222bf215546Sopenharmony_ciselect_line( struct draw_stage *stage, struct prim_header *prim ) 223bf215546Sopenharmony_ci{ 224bf215546Sopenharmony_ci struct feedback_stage *fs = feedback_stage(stage); 225bf215546Sopenharmony_ci _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] ); 226bf215546Sopenharmony_ci _mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] ); 227bf215546Sopenharmony_ci} 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_cistatic void 231bf215546Sopenharmony_ciselect_point( struct draw_stage *stage, struct prim_header *prim ) 232bf215546Sopenharmony_ci{ 233bf215546Sopenharmony_ci struct feedback_stage *fs = feedback_stage(stage); 234bf215546Sopenharmony_ci _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] ); 235bf215546Sopenharmony_ci} 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_cistatic void 239bf215546Sopenharmony_ciselect_flush( struct draw_stage *stage, unsigned flags ) 240bf215546Sopenharmony_ci{ 241bf215546Sopenharmony_ci /* no-op */ 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_cistatic void 246bf215546Sopenharmony_ciselect_reset_stipple_counter( struct draw_stage *stage ) 247bf215546Sopenharmony_ci{ 248bf215546Sopenharmony_ci /* no-op */ 249bf215546Sopenharmony_ci} 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_cistatic void 252bf215546Sopenharmony_ciselect_destroy( struct draw_stage *stage ) 253bf215546Sopenharmony_ci{ 254bf215546Sopenharmony_ci FREE(stage); 255bf215546Sopenharmony_ci} 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci/** 259bf215546Sopenharmony_ci * Create GL selection mode drawing stage. 260bf215546Sopenharmony_ci */ 261bf215546Sopenharmony_cistatic struct draw_stage * 262bf215546Sopenharmony_cidraw_glselect_stage(struct gl_context *ctx, struct draw_context *draw) 263bf215546Sopenharmony_ci{ 264bf215546Sopenharmony_ci struct feedback_stage *fs = CALLOC_STRUCT(feedback_stage); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci fs->stage.draw = draw; 267bf215546Sopenharmony_ci fs->stage.next = NULL; 268bf215546Sopenharmony_ci fs->stage.point = select_point; 269bf215546Sopenharmony_ci fs->stage.line = select_line; 270bf215546Sopenharmony_ci fs->stage.tri = select_tri; 271bf215546Sopenharmony_ci fs->stage.flush = select_flush; 272bf215546Sopenharmony_ci fs->stage.reset_stipple_counter = select_reset_stipple_counter; 273bf215546Sopenharmony_ci fs->stage.destroy = select_destroy; 274bf215546Sopenharmony_ci fs->ctx = ctx; 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci return &fs->stage; 277bf215546Sopenharmony_ci} 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_civoid 281bf215546Sopenharmony_cist_RenderMode(struct gl_context *ctx, GLenum newMode ) 282bf215546Sopenharmony_ci{ 283bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 284bf215546Sopenharmony_ci struct draw_context *draw = st_get_draw_context(st); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci if (!st->draw) 287bf215546Sopenharmony_ci return; 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci if (newMode == GL_RENDER) { 290bf215546Sopenharmony_ci /* restore normal VBO draw function */ 291bf215546Sopenharmony_ci st_init_draw_functions(st->screen, &ctx->Driver); 292bf215546Sopenharmony_ci } 293bf215546Sopenharmony_ci else if (newMode == GL_SELECT) { 294bf215546Sopenharmony_ci if (ctx->Const.HardwareAcceleratedSelect) 295bf215546Sopenharmony_ci st_init_hw_select_draw_functions(st->screen, &ctx->Driver); 296bf215546Sopenharmony_ci else { 297bf215546Sopenharmony_ci if (!st->selection_stage) 298bf215546Sopenharmony_ci st->selection_stage = draw_glselect_stage(ctx, draw); 299bf215546Sopenharmony_ci draw_set_rasterize_stage(draw, st->selection_stage); 300bf215546Sopenharmony_ci /* Plug in new vbo draw function */ 301bf215546Sopenharmony_ci ctx->Driver.DrawGallium = _mesa_draw_gallium_fallback; 302bf215546Sopenharmony_ci ctx->Driver.DrawGalliumMultiMode = _mesa_draw_gallium_multimode_fallback; 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci else { 306bf215546Sopenharmony_ci struct gl_program *vp = st->ctx->VertexProgram._Current; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (!st->feedback_stage) 309bf215546Sopenharmony_ci st->feedback_stage = draw_glfeedback_stage(ctx, draw); 310bf215546Sopenharmony_ci draw_set_rasterize_stage(draw, st->feedback_stage); 311bf215546Sopenharmony_ci /* Plug in new vbo draw function */ 312bf215546Sopenharmony_ci ctx->Driver.DrawGallium = _mesa_draw_gallium_fallback; 313bf215546Sopenharmony_ci ctx->Driver.DrawGalliumMultiMode = _mesa_draw_gallium_multimode_fallback; 314bf215546Sopenharmony_ci /* need to generate/use a vertex program that emits pos/color/tex */ 315bf215546Sopenharmony_ci if (vp) 316bf215546Sopenharmony_ci st->dirty |= ST_NEW_VERTEX_PROGRAM(st, vp); 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci /* Restore geometry shader states when leaving GL_SELECT mode. */ 320bf215546Sopenharmony_ci if (ctx->RenderMode == GL_SELECT && ctx->Const.HardwareAcceleratedSelect) 321bf215546Sopenharmony_ci st->dirty |= ST_NEW_GS_SSBOS | ST_NEW_GS_CONSTANTS | ST_NEW_GS_STATE; 322bf215546Sopenharmony_ci} 323