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 * Interface between 'draw' module's output and the softpipe rasterizer/setup 30bf215546Sopenharmony_ci * code. When the 'draw' module has finished filling a vertex buffer, the 31bf215546Sopenharmony_ci * draw_arrays() functions below will be called. Loop over the vertices and 32bf215546Sopenharmony_ci * call the point/line/tri setup functions. 33bf215546Sopenharmony_ci * 34bf215546Sopenharmony_ci * Authors 35bf215546Sopenharmony_ci * Brian Paul 36bf215546Sopenharmony_ci */ 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "sp_context.h" 40bf215546Sopenharmony_ci#include "sp_setup.h" 41bf215546Sopenharmony_ci#include "sp_state.h" 42bf215546Sopenharmony_ci#include "sp_prim_vbuf.h" 43bf215546Sopenharmony_ci#include "draw/draw_context.h" 44bf215546Sopenharmony_ci#include "draw/draw_vbuf.h" 45bf215546Sopenharmony_ci#include "util/u_memory.h" 46bf215546Sopenharmony_ci#include "util/u_prim.h" 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci#define SP_MAX_VBUF_INDEXES 1024 50bf215546Sopenharmony_ci#define SP_MAX_VBUF_SIZE 4096 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_citypedef const float (*cptrf4)[4]; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/** 55bf215546Sopenharmony_ci * Subclass of vbuf_render. 56bf215546Sopenharmony_ci */ 57bf215546Sopenharmony_cistruct softpipe_vbuf_render 58bf215546Sopenharmony_ci{ 59bf215546Sopenharmony_ci struct vbuf_render base; 60bf215546Sopenharmony_ci struct softpipe_context *softpipe; 61bf215546Sopenharmony_ci struct setup_context *setup; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci enum pipe_prim_type prim; 64bf215546Sopenharmony_ci uint vertex_size; 65bf215546Sopenharmony_ci uint nr_vertices; 66bf215546Sopenharmony_ci uint vertex_buffer_size; 67bf215546Sopenharmony_ci void *vertex_buffer; 68bf215546Sopenharmony_ci}; 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci/** cast wrapper */ 72bf215546Sopenharmony_cistatic struct softpipe_vbuf_render * 73bf215546Sopenharmony_cisoftpipe_vbuf_render(struct vbuf_render *vbr) 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci return (struct softpipe_vbuf_render *) vbr; 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci/** This tells the draw module about our desired vertex layout */ 80bf215546Sopenharmony_cistatic const struct vertex_info * 81bf215546Sopenharmony_cisp_vbuf_get_vertex_info(struct vbuf_render *vbr) 82bf215546Sopenharmony_ci{ 83bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 84bf215546Sopenharmony_ci return softpipe_get_vbuf_vertex_info(cvbr->softpipe); 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_cistatic boolean 89bf215546Sopenharmony_cisp_vbuf_allocate_vertices(struct vbuf_render *vbr, 90bf215546Sopenharmony_ci ushort vertex_size, ushort nr_vertices) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 93bf215546Sopenharmony_ci unsigned size = vertex_size * nr_vertices; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci if (cvbr->vertex_buffer_size < size) { 96bf215546Sopenharmony_ci align_free(cvbr->vertex_buffer); 97bf215546Sopenharmony_ci cvbr->vertex_buffer = align_malloc(size, 16); 98bf215546Sopenharmony_ci cvbr->vertex_buffer_size = size; 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci cvbr->vertex_size = vertex_size; 102bf215546Sopenharmony_ci cvbr->nr_vertices = nr_vertices; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci return cvbr->vertex_buffer != NULL; 105bf215546Sopenharmony_ci} 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_cistatic void 109bf215546Sopenharmony_cisp_vbuf_release_vertices(struct vbuf_render *vbr) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci /* keep the old allocation for next time */ 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_cistatic void * 116bf215546Sopenharmony_cisp_vbuf_map_vertices(struct vbuf_render *vbr) 117bf215546Sopenharmony_ci{ 118bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 119bf215546Sopenharmony_ci return cvbr->vertex_buffer; 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistatic void 124bf215546Sopenharmony_cisp_vbuf_unmap_vertices(struct vbuf_render *vbr, 125bf215546Sopenharmony_ci ushort min_index, 126bf215546Sopenharmony_ci ushort max_index ) 127bf215546Sopenharmony_ci{ 128bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 129bf215546Sopenharmony_ci assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size ); 130bf215546Sopenharmony_ci (void) cvbr; 131bf215546Sopenharmony_ci /* do nothing */ 132bf215546Sopenharmony_ci} 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_cistatic void 136bf215546Sopenharmony_cisp_vbuf_set_primitive(struct vbuf_render *vbr, enum pipe_prim_type prim) 137bf215546Sopenharmony_ci{ 138bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 139bf215546Sopenharmony_ci struct setup_context *setup_ctx = cvbr->setup; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci sp_setup_prepare( setup_ctx ); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci cvbr->softpipe->reduced_prim = u_reduced_prim(prim); 144bf215546Sopenharmony_ci cvbr->prim = prim; 145bf215546Sopenharmony_ci} 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_cistatic inline cptrf4 get_vert( const void *vertex_buffer, 149bf215546Sopenharmony_ci int index, 150bf215546Sopenharmony_ci int stride ) 151bf215546Sopenharmony_ci{ 152bf215546Sopenharmony_ci return (cptrf4)((char *)vertex_buffer + index * stride); 153bf215546Sopenharmony_ci} 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci/** 157bf215546Sopenharmony_ci * draw elements / indexed primitives 158bf215546Sopenharmony_ci */ 159bf215546Sopenharmony_cistatic void 160bf215546Sopenharmony_cisp_vbuf_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr) 161bf215546Sopenharmony_ci{ 162bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 163bf215546Sopenharmony_ci struct softpipe_context *softpipe = cvbr->softpipe; 164bf215546Sopenharmony_ci const unsigned stride = softpipe->vertex_info.size * sizeof(float); 165bf215546Sopenharmony_ci const void *vertex_buffer = cvbr->vertex_buffer; 166bf215546Sopenharmony_ci struct setup_context *setup = cvbr->setup; 167bf215546Sopenharmony_ci const boolean flatshade_first = softpipe->rasterizer->flatshade_first; 168bf215546Sopenharmony_ci unsigned i; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci switch (cvbr->prim) { 171bf215546Sopenharmony_ci case PIPE_PRIM_POINTS: 172bf215546Sopenharmony_ci for (i = 0; i < nr; i++) { 173bf215546Sopenharmony_ci sp_setup_point( setup, 174bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 175bf215546Sopenharmony_ci } 176bf215546Sopenharmony_ci break; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci case PIPE_PRIM_LINES: 179bf215546Sopenharmony_ci for (i = 1; i < nr; i += 2) { 180bf215546Sopenharmony_ci sp_setup_line( setup, 181bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 182bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci break; 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP: 187bf215546Sopenharmony_ci for (i = 1; i < nr; i ++) { 188bf215546Sopenharmony_ci sp_setup_line( setup, 189bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 190bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 191bf215546Sopenharmony_ci } 192bf215546Sopenharmony_ci break; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci case PIPE_PRIM_LINE_LOOP: 195bf215546Sopenharmony_ci for (i = 1; i < nr; i ++) { 196bf215546Sopenharmony_ci sp_setup_line( setup, 197bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 198bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci if (nr) { 201bf215546Sopenharmony_ci sp_setup_line( setup, 202bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[nr-1], stride), 203bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[0], stride) ); 204bf215546Sopenharmony_ci } 205bf215546Sopenharmony_ci break; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES: 208bf215546Sopenharmony_ci for (i = 2; i < nr; i += 3) { 209bf215546Sopenharmony_ci sp_setup_tri( setup, 210bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-2], stride), 211bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 212bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci break; 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP: 217bf215546Sopenharmony_ci if (flatshade_first) { 218bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 219bf215546Sopenharmony_ci /* emit first triangle vertex as first triangle vertex */ 220bf215546Sopenharmony_ci sp_setup_tri( setup, 221bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-2], stride), 222bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i+(i&1)-1], stride), 223bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-(i&1)], stride) ); 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci else { 228bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 229bf215546Sopenharmony_ci /* emit last triangle vertex as last triangle vertex */ 230bf215546Sopenharmony_ci sp_setup_tri( setup, 231bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i+(i&1)-2], stride), 232bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-(i&1)-1], stride), 233bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 234bf215546Sopenharmony_ci } 235bf215546Sopenharmony_ci } 236bf215546Sopenharmony_ci break; 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_FAN: 239bf215546Sopenharmony_ci if (flatshade_first) { 240bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 241bf215546Sopenharmony_ci /* emit first non-spoke vertex as first vertex */ 242bf215546Sopenharmony_ci sp_setup_tri( setup, 243bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 244bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride), 245bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[0], stride) ); 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci else { 249bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 250bf215546Sopenharmony_ci /* emit last non-spoke vertex as last vertex */ 251bf215546Sopenharmony_ci sp_setup_tri( setup, 252bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[0], stride), 253bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 254bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 255bf215546Sopenharmony_ci } 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci break; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci case PIPE_PRIM_QUADS: 260bf215546Sopenharmony_ci /* GL quads don't follow provoking vertex convention */ 261bf215546Sopenharmony_ci if (flatshade_first) { 262bf215546Sopenharmony_ci /* emit last quad vertex as first triangle vertex */ 263bf215546Sopenharmony_ci for (i = 3; i < nr; i += 4) { 264bf215546Sopenharmony_ci sp_setup_tri( setup, 265bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride), 266bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-3], stride), 267bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-2], stride) ); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci sp_setup_tri( setup, 270bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride), 271bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-2], stride), 272bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride) ); 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci else { 276bf215546Sopenharmony_ci /* emit last quad vertex as last triangle vertex */ 277bf215546Sopenharmony_ci for (i = 3; i < nr; i += 4) { 278bf215546Sopenharmony_ci sp_setup_tri( setup, 279bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-3], stride), 280bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-2], stride), 281bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci sp_setup_tri( setup, 284bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-2], stride), 285bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 286bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci break; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci case PIPE_PRIM_QUAD_STRIP: 292bf215546Sopenharmony_ci /* GL quad strips don't follow provoking vertex convention */ 293bf215546Sopenharmony_ci if (flatshade_first) { 294bf215546Sopenharmony_ci /* emit last quad vertex as first triangle vertex */ 295bf215546Sopenharmony_ci for (i = 3; i < nr; i += 2) { 296bf215546Sopenharmony_ci sp_setup_tri( setup, 297bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride), 298bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-3], stride), 299bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-2], stride) ); 300bf215546Sopenharmony_ci sp_setup_tri( setup, 301bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride), 302bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 303bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-3], stride) ); 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci } 306bf215546Sopenharmony_ci else { 307bf215546Sopenharmony_ci /* emit last quad vertex as last triangle vertex */ 308bf215546Sopenharmony_ci for (i = 3; i < nr; i += 2) { 309bf215546Sopenharmony_ci sp_setup_tri( setup, 310bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-3], stride), 311bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-2], stride), 312bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 313bf215546Sopenharmony_ci sp_setup_tri( setup, 314bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 315bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-3], stride), 316bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci } 319bf215546Sopenharmony_ci break; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci case PIPE_PRIM_POLYGON: 322bf215546Sopenharmony_ci /* Almost same as tri fan but the _first_ vertex specifies the flat 323bf215546Sopenharmony_ci * shading color. 324bf215546Sopenharmony_ci */ 325bf215546Sopenharmony_ci if (flatshade_first) { 326bf215546Sopenharmony_ci /* emit first polygon vertex as first triangle vertex */ 327bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 328bf215546Sopenharmony_ci sp_setup_tri( setup, 329bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[0], stride), 330bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 331bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride) ); 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci } 334bf215546Sopenharmony_ci else { 335bf215546Sopenharmony_ci /* emit first polygon vertex as last triangle vertex */ 336bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 337bf215546Sopenharmony_ci sp_setup_tri( setup, 338bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-1], stride), 339bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[i-0], stride), 340bf215546Sopenharmony_ci get_vert(vertex_buffer, indices[0], stride) ); 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci break; 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci default: 346bf215546Sopenharmony_ci assert(0); 347bf215546Sopenharmony_ci } 348bf215546Sopenharmony_ci} 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci/** 352bf215546Sopenharmony_ci * This function is hit when the draw module is working in pass-through mode. 353bf215546Sopenharmony_ci * It's up to us to convert the vertex array into point/line/tri prims. 354bf215546Sopenharmony_ci */ 355bf215546Sopenharmony_cistatic void 356bf215546Sopenharmony_cisp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) 357bf215546Sopenharmony_ci{ 358bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 359bf215546Sopenharmony_ci struct softpipe_context *softpipe = cvbr->softpipe; 360bf215546Sopenharmony_ci struct setup_context *setup = cvbr->setup; 361bf215546Sopenharmony_ci const unsigned stride = softpipe->vertex_info.size * sizeof(float); 362bf215546Sopenharmony_ci const void *vertex_buffer = 363bf215546Sopenharmony_ci (void *) get_vert(cvbr->vertex_buffer, start, stride); 364bf215546Sopenharmony_ci const boolean flatshade_first = softpipe->rasterizer->flatshade_first; 365bf215546Sopenharmony_ci unsigned i; 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci switch (cvbr->prim) { 368bf215546Sopenharmony_ci case PIPE_PRIM_POINTS: 369bf215546Sopenharmony_ci for (i = 0; i < nr; i++) { 370bf215546Sopenharmony_ci sp_setup_point( setup, 371bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci break; 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci case PIPE_PRIM_LINES: 376bf215546Sopenharmony_ci for (i = 1; i < nr; i += 2) { 377bf215546Sopenharmony_ci sp_setup_line( setup, 378bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 379bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 380bf215546Sopenharmony_ci } 381bf215546Sopenharmony_ci break; 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci case PIPE_PRIM_LINES_ADJACENCY: 384bf215546Sopenharmony_ci for (i = 3; i < nr; i += 4) { 385bf215546Sopenharmony_ci sp_setup_line( setup, 386bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride), 387bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride) ); 388bf215546Sopenharmony_ci } 389bf215546Sopenharmony_ci break; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP: 392bf215546Sopenharmony_ci for (i = 1; i < nr; i ++) { 393bf215546Sopenharmony_ci sp_setup_line( setup, 394bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 395bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 396bf215546Sopenharmony_ci } 397bf215546Sopenharmony_ci break; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP_ADJACENCY: 400bf215546Sopenharmony_ci for (i = 3; i < nr; i++) { 401bf215546Sopenharmony_ci sp_setup_line( setup, 402bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride), 403bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride) ); 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci break; 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci case PIPE_PRIM_LINE_LOOP: 408bf215546Sopenharmony_ci for (i = 1; i < nr; i ++) { 409bf215546Sopenharmony_ci sp_setup_line( setup, 410bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 411bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 412bf215546Sopenharmony_ci } 413bf215546Sopenharmony_ci if (nr) { 414bf215546Sopenharmony_ci sp_setup_line( setup, 415bf215546Sopenharmony_ci get_vert(vertex_buffer, nr-1, stride), 416bf215546Sopenharmony_ci get_vert(vertex_buffer, 0, stride) ); 417bf215546Sopenharmony_ci } 418bf215546Sopenharmony_ci break; 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES: 421bf215546Sopenharmony_ci for (i = 2; i < nr; i += 3) { 422bf215546Sopenharmony_ci sp_setup_tri( setup, 423bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride), 424bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 425bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci break; 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES_ADJACENCY: 430bf215546Sopenharmony_ci for (i = 5; i < nr; i += 6) { 431bf215546Sopenharmony_ci sp_setup_tri( setup, 432bf215546Sopenharmony_ci get_vert(vertex_buffer, i-5, stride), 433bf215546Sopenharmony_ci get_vert(vertex_buffer, i-3, stride), 434bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride) ); 435bf215546Sopenharmony_ci } 436bf215546Sopenharmony_ci break; 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP: 439bf215546Sopenharmony_ci if (flatshade_first) { 440bf215546Sopenharmony_ci for (i = 2; i < nr; i++) { 441bf215546Sopenharmony_ci /* emit first triangle vertex as first triangle vertex */ 442bf215546Sopenharmony_ci sp_setup_tri( setup, 443bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride), 444bf215546Sopenharmony_ci get_vert(vertex_buffer, i+(i&1)-1, stride), 445bf215546Sopenharmony_ci get_vert(vertex_buffer, i-(i&1), stride) ); 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci } 448bf215546Sopenharmony_ci else { 449bf215546Sopenharmony_ci for (i = 2; i < nr; i++) { 450bf215546Sopenharmony_ci /* emit last triangle vertex as last triangle vertex */ 451bf215546Sopenharmony_ci sp_setup_tri( setup, 452bf215546Sopenharmony_ci get_vert(vertex_buffer, i+(i&1)-2, stride), 453bf215546Sopenharmony_ci get_vert(vertex_buffer, i-(i&1)-1, stride), 454bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 455bf215546Sopenharmony_ci } 456bf215546Sopenharmony_ci } 457bf215546Sopenharmony_ci break; 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 460bf215546Sopenharmony_ci if (flatshade_first) { 461bf215546Sopenharmony_ci for (i = 5; i < nr; i += 2) { 462bf215546Sopenharmony_ci /* emit first triangle vertex as first triangle vertex */ 463bf215546Sopenharmony_ci sp_setup_tri( setup, 464bf215546Sopenharmony_ci get_vert(vertex_buffer, i-5, stride), 465bf215546Sopenharmony_ci get_vert(vertex_buffer, i+(i&1)*2-3, stride), 466bf215546Sopenharmony_ci get_vert(vertex_buffer, i-(i&1)*2-1, stride) ); 467bf215546Sopenharmony_ci } 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci else { 470bf215546Sopenharmony_ci for (i = 5; i < nr; i += 2) { 471bf215546Sopenharmony_ci /* emit last triangle vertex as last triangle vertex */ 472bf215546Sopenharmony_ci sp_setup_tri( setup, 473bf215546Sopenharmony_ci get_vert(vertex_buffer, i+(i&1)*2-5, stride), 474bf215546Sopenharmony_ci get_vert(vertex_buffer, i-(i&1)*2-3, stride), 475bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride) ); 476bf215546Sopenharmony_ci } 477bf215546Sopenharmony_ci } 478bf215546Sopenharmony_ci break; 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_FAN: 481bf215546Sopenharmony_ci if (flatshade_first) { 482bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 483bf215546Sopenharmony_ci /* emit first non-spoke vertex as first vertex */ 484bf215546Sopenharmony_ci sp_setup_tri( setup, 485bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 486bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride), 487bf215546Sopenharmony_ci get_vert(vertex_buffer, 0, stride) ); 488bf215546Sopenharmony_ci } 489bf215546Sopenharmony_ci } 490bf215546Sopenharmony_ci else { 491bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 492bf215546Sopenharmony_ci /* emit last non-spoke vertex as last vertex */ 493bf215546Sopenharmony_ci sp_setup_tri( setup, 494bf215546Sopenharmony_ci get_vert(vertex_buffer, 0, stride), 495bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 496bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 497bf215546Sopenharmony_ci } 498bf215546Sopenharmony_ci } 499bf215546Sopenharmony_ci break; 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci case PIPE_PRIM_QUADS: 502bf215546Sopenharmony_ci /* GL quads don't follow provoking vertex convention */ 503bf215546Sopenharmony_ci if (flatshade_first) { 504bf215546Sopenharmony_ci /* emit last quad vertex as first triangle vertex */ 505bf215546Sopenharmony_ci for (i = 3; i < nr; i += 4) { 506bf215546Sopenharmony_ci sp_setup_tri( setup, 507bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride), 508bf215546Sopenharmony_ci get_vert(vertex_buffer, i-3, stride), 509bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride) ); 510bf215546Sopenharmony_ci sp_setup_tri( setup, 511bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride), 512bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride), 513bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride) ); 514bf215546Sopenharmony_ci } 515bf215546Sopenharmony_ci } 516bf215546Sopenharmony_ci else { 517bf215546Sopenharmony_ci /* emit last quad vertex as last triangle vertex */ 518bf215546Sopenharmony_ci for (i = 3; i < nr; i += 4) { 519bf215546Sopenharmony_ci sp_setup_tri( setup, 520bf215546Sopenharmony_ci get_vert(vertex_buffer, i-3, stride), 521bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride), 522bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 523bf215546Sopenharmony_ci sp_setup_tri( setup, 524bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride), 525bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 526bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 527bf215546Sopenharmony_ci } 528bf215546Sopenharmony_ci } 529bf215546Sopenharmony_ci break; 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci case PIPE_PRIM_QUAD_STRIP: 532bf215546Sopenharmony_ci /* GL quad strips don't follow provoking vertex convention */ 533bf215546Sopenharmony_ci if (flatshade_first) { 534bf215546Sopenharmony_ci /* emit last quad vertex as first triangle vertex */ 535bf215546Sopenharmony_ci for (i = 3; i < nr; i += 2) { 536bf215546Sopenharmony_ci sp_setup_tri( setup, 537bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride), 538bf215546Sopenharmony_ci get_vert(vertex_buffer, i-3, stride), 539bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride) ); 540bf215546Sopenharmony_ci sp_setup_tri( setup, 541bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride), 542bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 543bf215546Sopenharmony_ci get_vert(vertex_buffer, i-3, stride) ); 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci } 546bf215546Sopenharmony_ci else { 547bf215546Sopenharmony_ci /* emit last quad vertex as last triangle vertex */ 548bf215546Sopenharmony_ci for (i = 3; i < nr; i += 2) { 549bf215546Sopenharmony_ci sp_setup_tri( setup, 550bf215546Sopenharmony_ci get_vert(vertex_buffer, i-3, stride), 551bf215546Sopenharmony_ci get_vert(vertex_buffer, i-2, stride), 552bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 553bf215546Sopenharmony_ci sp_setup_tri( setup, 554bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 555bf215546Sopenharmony_ci get_vert(vertex_buffer, i-3, stride), 556bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 557bf215546Sopenharmony_ci } 558bf215546Sopenharmony_ci } 559bf215546Sopenharmony_ci break; 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci case PIPE_PRIM_POLYGON: 562bf215546Sopenharmony_ci /* Almost same as tri fan but the _first_ vertex specifies the flat 563bf215546Sopenharmony_ci * shading color. 564bf215546Sopenharmony_ci */ 565bf215546Sopenharmony_ci if (flatshade_first) { 566bf215546Sopenharmony_ci /* emit first polygon vertex as first triangle vertex */ 567bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 568bf215546Sopenharmony_ci sp_setup_tri( setup, 569bf215546Sopenharmony_ci get_vert(vertex_buffer, 0, stride), 570bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 571bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride) ); 572bf215546Sopenharmony_ci } 573bf215546Sopenharmony_ci } 574bf215546Sopenharmony_ci else { 575bf215546Sopenharmony_ci /* emit first polygon vertex as last triangle vertex */ 576bf215546Sopenharmony_ci for (i = 2; i < nr; i += 1) { 577bf215546Sopenharmony_ci sp_setup_tri( setup, 578bf215546Sopenharmony_ci get_vert(vertex_buffer, i-1, stride), 579bf215546Sopenharmony_ci get_vert(vertex_buffer, i-0, stride), 580bf215546Sopenharmony_ci get_vert(vertex_buffer, 0, stride) ); 581bf215546Sopenharmony_ci } 582bf215546Sopenharmony_ci } 583bf215546Sopenharmony_ci break; 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci default: 586bf215546Sopenharmony_ci assert(0); 587bf215546Sopenharmony_ci } 588bf215546Sopenharmony_ci} 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_ci/* 591bf215546Sopenharmony_ci * FIXME: it is unclear if primitives_storage_needed (which is generally 592bf215546Sopenharmony_ci * the same as pipe query num_primitives_generated) should increase 593bf215546Sopenharmony_ci * if SO is disabled for d3d10, but for GL we definitely need to 594bf215546Sopenharmony_ci * increase num_primitives_generated and this is only called for active 595bf215546Sopenharmony_ci * SO. If it must not increase for d3d10 need to disambiguate the counters 596bf215546Sopenharmony_ci * in the driver and do some work for getting correct values, if it should 597bf215546Sopenharmony_ci * increase too should call this from outside streamout code. 598bf215546Sopenharmony_ci */ 599bf215546Sopenharmony_cistatic void 600bf215546Sopenharmony_cisp_vbuf_so_info(struct vbuf_render *vbr, uint stream, uint primitives, uint prim_generated) 601bf215546Sopenharmony_ci{ 602bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 603bf215546Sopenharmony_ci struct softpipe_context *softpipe = cvbr->softpipe; 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci softpipe->so_stats[stream].num_primitives_written += primitives; 606bf215546Sopenharmony_ci softpipe->so_stats[stream].primitives_storage_needed += prim_generated; 607bf215546Sopenharmony_ci} 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_cistatic void 610bf215546Sopenharmony_cisp_vbuf_pipeline_statistics( 611bf215546Sopenharmony_ci struct vbuf_render *vbr, 612bf215546Sopenharmony_ci const struct pipe_query_data_pipeline_statistics *stats) 613bf215546Sopenharmony_ci{ 614bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 615bf215546Sopenharmony_ci struct softpipe_context *softpipe = cvbr->softpipe; 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ci softpipe->pipeline_statistics.ia_vertices += 618bf215546Sopenharmony_ci stats->ia_vertices; 619bf215546Sopenharmony_ci softpipe->pipeline_statistics.ia_primitives += 620bf215546Sopenharmony_ci stats->ia_primitives; 621bf215546Sopenharmony_ci softpipe->pipeline_statistics.vs_invocations += 622bf215546Sopenharmony_ci stats->vs_invocations; 623bf215546Sopenharmony_ci softpipe->pipeline_statistics.gs_invocations += 624bf215546Sopenharmony_ci stats->gs_invocations; 625bf215546Sopenharmony_ci softpipe->pipeline_statistics.gs_primitives += 626bf215546Sopenharmony_ci stats->gs_primitives; 627bf215546Sopenharmony_ci softpipe->pipeline_statistics.c_invocations += 628bf215546Sopenharmony_ci stats->c_invocations; 629bf215546Sopenharmony_ci} 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci 632bf215546Sopenharmony_cistatic void 633bf215546Sopenharmony_cisp_vbuf_destroy(struct vbuf_render *vbr) 634bf215546Sopenharmony_ci{ 635bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); 636bf215546Sopenharmony_ci if (cvbr->vertex_buffer) 637bf215546Sopenharmony_ci align_free(cvbr->vertex_buffer); 638bf215546Sopenharmony_ci sp_setup_destroy_context(cvbr->setup); 639bf215546Sopenharmony_ci FREE(cvbr); 640bf215546Sopenharmony_ci} 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci/** 644bf215546Sopenharmony_ci * Create the post-transform vertex handler for the given context. 645bf215546Sopenharmony_ci */ 646bf215546Sopenharmony_cistruct vbuf_render * 647bf215546Sopenharmony_cisp_create_vbuf_backend(struct softpipe_context *sp) 648bf215546Sopenharmony_ci{ 649bf215546Sopenharmony_ci struct softpipe_vbuf_render *cvbr = CALLOC_STRUCT(softpipe_vbuf_render); 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_ci assert(sp->draw); 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci cvbr->base.max_indices = SP_MAX_VBUF_INDEXES; 654bf215546Sopenharmony_ci cvbr->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE; 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_ci cvbr->base.get_vertex_info = sp_vbuf_get_vertex_info; 657bf215546Sopenharmony_ci cvbr->base.allocate_vertices = sp_vbuf_allocate_vertices; 658bf215546Sopenharmony_ci cvbr->base.map_vertices = sp_vbuf_map_vertices; 659bf215546Sopenharmony_ci cvbr->base.unmap_vertices = sp_vbuf_unmap_vertices; 660bf215546Sopenharmony_ci cvbr->base.set_primitive = sp_vbuf_set_primitive; 661bf215546Sopenharmony_ci cvbr->base.draw_elements = sp_vbuf_draw_elements; 662bf215546Sopenharmony_ci cvbr->base.draw_arrays = sp_vbuf_draw_arrays; 663bf215546Sopenharmony_ci cvbr->base.release_vertices = sp_vbuf_release_vertices; 664bf215546Sopenharmony_ci cvbr->base.set_stream_output_info = sp_vbuf_so_info; 665bf215546Sopenharmony_ci cvbr->base.pipeline_statistics = sp_vbuf_pipeline_statistics; 666bf215546Sopenharmony_ci cvbr->base.destroy = sp_vbuf_destroy; 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci cvbr->softpipe = sp; 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci cvbr->setup = sp_setup_create_context(cvbr->softpipe); 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci return &cvbr->base; 673bf215546Sopenharmony_ci} 674