intel_tris.c revision 60d762aa625095a8c1f9597d8530bb5a6fa61b4c
1/************************************************************************** 2 * 3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include "glheader.h" 29#include "context.h" 30#include "macros.h" 31#include "enums.h" 32#include "texobj.h" 33#include "state.h" 34#include "dd.h" 35 36#include "swrast/swrast.h" 37#include "swrast_setup/swrast_setup.h" 38#include "tnl/t_context.h" 39#include "tnl/t_pipeline.h" 40#include "tnl/t_vertex.h" 41 42#include "intel_screen.h" 43#include "intel_context.h" 44#include "intel_tris.h" 45#include "intel_batchbuffer.h" 46#include "intel_buffers.h" 47#include "intel_reg.h" 48#include "intel_span.h" 49#include "intel_tex.h" 50 51static void intelRenderPrimitive(GLcontext * ctx, GLenum prim); 52static void intelRasterPrimitive(GLcontext * ctx, GLenum rprim, 53 GLuint hwprim); 54 55/* 56 */ 57static void 58intel_flush_inline_primitive(struct intel_context *intel) 59{ 60 GLuint used = intel->batch->ptr - intel->prim.start_ptr; 61 62 assert(intel->prim.primitive != ~0); 63 64/* _mesa_printf("/\n"); */ 65 66 if (used < 8) 67 goto do_discard; 68 69 *(int *) intel->prim.start_ptr = (_3DPRIMITIVE | 70 intel->prim.primitive | (used / 4 - 2)); 71 72 goto finished; 73 74 do_discard: 75 intel->batch->ptr -= used; 76 77 finished: 78 intel->prim.primitive = ~0; 79 intel->prim.start_ptr = 0; 80 intel->prim.flush = 0; 81} 82 83 84/* Emit a primitive referencing vertices in a vertex buffer. 85 */ 86void 87intelStartInlinePrimitive(struct intel_context *intel, 88 GLuint prim, GLuint batch_flags) 89{ 90 BATCH_LOCALS; 91 92 intel->vtbl.emit_state(intel); 93 94 /* Need to make sure at the very least that we don't wrap 95 * batchbuffers in BEGIN_BATCH below, otherwise the primitive will 96 * be emitted to a batchbuffer missing the required full-state 97 * preamble. 98 */ 99 if (intel_batchbuffer_space(intel->batch) < 100) { 100 intel_batchbuffer_flush(intel->batch); 101 intel->vtbl.emit_state(intel); 102 } 103 104/* _mesa_printf("%s *", __progname); */ 105 106 intel_wait_flips(intel, batch_flags); 107 108 /* Emit a slot which will be filled with the inline primitive 109 * command later. 110 */ 111 BEGIN_BATCH(2, batch_flags); 112 OUT_BATCH(0); 113 114 assert(intel->batch->id == intel->last_state_batch_id); 115 assert((intel->batch->dirty_state & (1<<1)) == 0); 116 117 intel->prim.start_ptr = intel->batch->ptr; 118 intel->prim.primitive = prim; 119 intel->prim.flush = intel_flush_inline_primitive; 120 121 OUT_BATCH(0); 122 ADVANCE_BATCH(); 123 124/* _mesa_printf(">"); */ 125} 126 127 128void 129intelWrapInlinePrimitive(struct intel_context *intel) 130{ 131 GLuint prim = intel->prim.primitive; 132 GLuint batchflags = intel->batch->flags; 133 134 intel_flush_inline_primitive(intel); 135 intel_batchbuffer_flush(intel->batch); 136 intelStartInlinePrimitive(intel, prim, batchflags); /* ??? */ 137} 138 139GLuint * 140intelExtendInlinePrimitive(struct intel_context *intel, GLuint dwords) 141{ 142 GLuint sz = dwords * sizeof(GLuint); 143 GLuint *ptr; 144 145 assert(intel->prim.flush == intel_flush_inline_primitive); 146 147 if (intel_batchbuffer_space(intel->batch) < sz) 148 intelWrapInlinePrimitive(intel); 149 150/* _mesa_printf("."); */ 151 152 intel->vtbl.assert_not_dirty(intel); 153 154 ptr = (GLuint *) intel->batch->ptr; 155 intel->batch->ptr += sz; 156 157 return ptr; 158} 159 160 161 162/*********************************************************************** 163 * Emit primitives as inline vertices * 164 ***********************************************************************/ 165 166#ifdef __i386__ 167#define COPY_DWORDS( j, vb, vertsize, v ) \ 168do { \ 169 int __tmp; \ 170 __asm__ __volatile__( "rep ; movsl" \ 171 : "=%c" (j), "=D" (vb), "=S" (__tmp) \ 172 : "0" (vertsize), \ 173 "D" ((long)vb), \ 174 "S" ((long)v) ); \ 175} while (0) 176#else 177#define COPY_DWORDS( j, vb, vertsize, v ) \ 178do { \ 179 for ( j = 0 ; j < vertsize ; j++ ) { \ 180 vb[j] = ((GLuint *)v)[j]; \ 181 } \ 182 vb += vertsize; \ 183} while (0) 184#endif 185 186static void 187intel_draw_quad(struct intel_context *intel, 188 intelVertexPtr v0, 189 intelVertexPtr v1, intelVertexPtr v2, intelVertexPtr v3) 190{ 191 GLuint vertsize = intel->vertex_size; 192 GLuint *vb = intelExtendInlinePrimitive(intel, 6 * vertsize); 193 int j; 194 195 COPY_DWORDS(j, vb, vertsize, v0); 196 COPY_DWORDS(j, vb, vertsize, v1); 197 198 /* If smooth shading, draw like a trifan which gives better 199 * rasterization. Otherwise draw as two triangles with provoking 200 * vertex in third position as required for flat shading. 201 */ 202 if (intel->ctx.Light.ShadeModel == GL_FLAT) { 203 COPY_DWORDS(j, vb, vertsize, v3); 204 COPY_DWORDS(j, vb, vertsize, v1); 205 } 206 else { 207 COPY_DWORDS(j, vb, vertsize, v2); 208 COPY_DWORDS(j, vb, vertsize, v0); 209 } 210 211 COPY_DWORDS(j, vb, vertsize, v2); 212 COPY_DWORDS(j, vb, vertsize, v3); 213} 214 215static void 216intel_draw_triangle(struct intel_context *intel, 217 intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2) 218{ 219 GLuint vertsize = intel->vertex_size; 220 GLuint *vb = intelExtendInlinePrimitive(intel, 3 * vertsize); 221 int j; 222 223 COPY_DWORDS(j, vb, vertsize, v0); 224 COPY_DWORDS(j, vb, vertsize, v1); 225 COPY_DWORDS(j, vb, vertsize, v2); 226} 227 228 229static void 230intel_draw_line(struct intel_context *intel, 231 intelVertexPtr v0, intelVertexPtr v1) 232{ 233 GLuint vertsize = intel->vertex_size; 234 GLuint *vb = intelExtendInlinePrimitive(intel, 2 * vertsize); 235 int j; 236 237 COPY_DWORDS(j, vb, vertsize, v0); 238 COPY_DWORDS(j, vb, vertsize, v1); 239} 240 241 242static void 243intel_draw_point(struct intel_context *intel, intelVertexPtr v0) 244{ 245 GLuint vertsize = intel->vertex_size; 246 GLuint *vb = intelExtendInlinePrimitive(intel, vertsize); 247 int j; 248 249 /* Adjust for sub pixel position -- still required for conform. */ 250 *(float *) &vb[0] = v0->v.x; 251 *(float *) &vb[1] = v0->v.y; 252 for (j = 2; j < vertsize; j++) 253 vb[j] = v0->ui[j]; 254} 255 256 257 258/*********************************************************************** 259 * Fixup for ARB_point_parameters * 260 ***********************************************************************/ 261 262/* Currently not working - VERT_ATTRIB_POINTSIZE isn't correctly 263 * represented in the fragment program InputsRead field. 264 */ 265static void 266intel_atten_point(struct intel_context *intel, intelVertexPtr v0) 267{ 268 GLcontext *ctx = &intel->ctx; 269 GLfloat psz[4], col[4], restore_psz, restore_alpha; 270 271 _tnl_get_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz); 272 _tnl_get_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col); 273 274 restore_psz = psz[0]; 275 restore_alpha = col[3]; 276 277 if (psz[0] >= ctx->Point.Threshold) { 278 psz[0] = MIN2(psz[0], ctx->Point.MaxSize); 279 } 280 else { 281 GLfloat dsize = psz[0] / ctx->Point.Threshold; 282 psz[0] = MAX2(ctx->Point.Threshold, ctx->Point.MinSize); 283 col[3] *= dsize * dsize; 284 } 285 286 if (psz[0] < 1.0) 287 psz[0] = 1.0; 288 289 if (restore_psz != psz[0] || restore_alpha != col[3]) { 290 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz); 291 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col); 292 293 intel_draw_point(intel, v0); 294 295 psz[0] = restore_psz; 296 col[3] = restore_alpha; 297 298 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz); 299 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col); 300 } 301 else 302 intel_draw_point(intel, v0); 303} 304 305 306 307 308 309/*********************************************************************** 310 * Fixup for I915 WPOS texture coordinate * 311 ***********************************************************************/ 312 313 314 315static void 316intel_wpos_triangle(struct intel_context *intel, 317 intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2) 318{ 319 GLuint offset = intel->wpos_offset; 320 GLuint size = intel->wpos_size; 321 322 __memcpy(((char *) v0) + offset, v0, size); 323 __memcpy(((char *) v1) + offset, v1, size); 324 __memcpy(((char *) v2) + offset, v2, size); 325 326 intel_draw_triangle(intel, v0, v1, v2); 327} 328 329 330static void 331intel_wpos_line(struct intel_context *intel, 332 intelVertexPtr v0, intelVertexPtr v1) 333{ 334 GLuint offset = intel->wpos_offset; 335 GLuint size = intel->wpos_size; 336 337 __memcpy(((char *) v0) + offset, v0, size); 338 __memcpy(((char *) v1) + offset, v1, size); 339 340 intel_draw_line(intel, v0, v1); 341} 342 343 344static void 345intel_wpos_point(struct intel_context *intel, intelVertexPtr v0) 346{ 347 GLuint offset = intel->wpos_offset; 348 GLuint size = intel->wpos_size; 349 350 __memcpy(((char *) v0) + offset, v0, size); 351 352 intel_draw_point(intel, v0); 353} 354 355 356 357 358 359 360/*********************************************************************** 361 * Macros for t_dd_tritmp.h to draw basic primitives * 362 ***********************************************************************/ 363 364#define TRI( a, b, c ) \ 365do { \ 366 if (DO_FALLBACK) \ 367 intel->draw_tri( intel, a, b, c ); \ 368 else \ 369 intel_draw_triangle( intel, a, b, c ); \ 370} while (0) 371 372#define QUAD( a, b, c, d ) \ 373do { \ 374 if (DO_FALLBACK) { \ 375 intel->draw_tri( intel, a, b, d ); \ 376 intel->draw_tri( intel, b, c, d ); \ 377 } else \ 378 intel_draw_quad( intel, a, b, c, d ); \ 379} while (0) 380 381#define LINE( v0, v1 ) \ 382do { \ 383 if (DO_FALLBACK) \ 384 intel->draw_line( intel, v0, v1 ); \ 385 else \ 386 intel_draw_line( intel, v0, v1 ); \ 387} while (0) 388 389#define POINT( v0 ) \ 390do { \ 391 if (DO_FALLBACK) \ 392 intel->draw_point( intel, v0 ); \ 393 else \ 394 intel_draw_point( intel, v0 ); \ 395} while (0) 396 397 398/*********************************************************************** 399 * Build render functions from dd templates * 400 ***********************************************************************/ 401 402#define INTEL_OFFSET_BIT 0x01 403#define INTEL_TWOSIDE_BIT 0x02 404#define INTEL_UNFILLED_BIT 0x04 405#define INTEL_FALLBACK_BIT 0x08 406#define INTEL_MAX_TRIFUNC 0x10 407 408 409static struct 410{ 411 tnl_points_func points; 412 tnl_line_func line; 413 tnl_triangle_func triangle; 414 tnl_quad_func quad; 415} rast_tab[INTEL_MAX_TRIFUNC]; 416 417 418#define DO_FALLBACK (IND & INTEL_FALLBACK_BIT) 419#define DO_OFFSET (IND & INTEL_OFFSET_BIT) 420#define DO_UNFILLED (IND & INTEL_UNFILLED_BIT) 421#define DO_TWOSIDE (IND & INTEL_TWOSIDE_BIT) 422#define DO_FLAT 0 423#define DO_TRI 1 424#define DO_QUAD 1 425#define DO_LINE 1 426#define DO_POINTS 1 427#define DO_FULL_QUAD 1 428 429#define HAVE_RGBA 1 430#define HAVE_SPEC 1 431#define HAVE_BACK_COLORS 0 432#define HAVE_HW_FLATSHADE 1 433#define VERTEX intelVertex 434#define TAB rast_tab 435 436/* Only used to pull back colors into vertices (ie, we know color is 437 * floating point). 438 */ 439#define INTEL_COLOR( dst, src ) \ 440do { \ 441 UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \ 442 UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \ 443 UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \ 444 UNCLAMPED_FLOAT_TO_UBYTE((dst)[3], (src)[3]); \ 445} while (0) 446 447#define INTEL_SPEC( dst, src ) \ 448do { \ 449 UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \ 450 UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \ 451 UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \ 452} while (0) 453 454 455#define DEPTH_SCALE intel->polygon_offset_scale 456#define UNFILLED_TRI unfilled_tri 457#define UNFILLED_QUAD unfilled_quad 458#define VERT_X(_v) _v->v.x 459#define VERT_Y(_v) _v->v.y 460#define VERT_Z(_v) _v->v.z 461#define AREA_IS_CCW( a ) (a > 0) 462#define GET_VERTEX(e) (intel->verts + (e * intel->vertex_size * sizeof(GLuint))) 463 464#define VERT_SET_RGBA( v, c ) if (coloroffset) INTEL_COLOR( v->ub4[coloroffset], c ) 465#define VERT_COPY_RGBA( v0, v1 ) if (coloroffset) v0->ui[coloroffset] = v1->ui[coloroffset] 466#define VERT_SAVE_RGBA( idx ) if (coloroffset) color[idx] = v[idx]->ui[coloroffset] 467#define VERT_RESTORE_RGBA( idx ) if (coloroffset) v[idx]->ui[coloroffset] = color[idx] 468 469#define VERT_SET_SPEC( v, c ) if (specoffset) INTEL_SPEC( v->ub4[specoffset], c ) 470#define VERT_COPY_SPEC( v0, v1 ) if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset]) 471#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset] 472#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] 473 474#define LOCAL_VARS(n) \ 475 struct intel_context *intel = intel_context(ctx); \ 476 GLuint color[n], spec[n]; \ 477 GLuint coloroffset = intel->coloroffset; \ 478 GLboolean specoffset = intel->specoffset; \ 479 (void) color; (void) spec; (void) coloroffset; (void) specoffset; 480 481 482/*********************************************************************** 483 * Helpers for rendering unfilled primitives * 484 ***********************************************************************/ 485 486static const GLuint hw_prim[GL_POLYGON + 1] = { 487 PRIM3D_POINTLIST, 488 PRIM3D_LINELIST, 489 PRIM3D_LINELIST, 490 PRIM3D_LINELIST, 491 PRIM3D_TRILIST, 492 PRIM3D_TRILIST, 493 PRIM3D_TRILIST, 494 PRIM3D_TRILIST, 495 PRIM3D_TRILIST, 496 PRIM3D_TRILIST 497}; 498 499#define RASTERIZE(x) intelRasterPrimitive( ctx, x, hw_prim[x] ) 500#define RENDER_PRIMITIVE intel->render_primitive 501#define TAG(x) x 502#define IND INTEL_FALLBACK_BIT 503#include "tnl_dd/t_dd_unfilled.h" 504#undef IND 505 506/*********************************************************************** 507 * Generate GL render functions * 508 ***********************************************************************/ 509 510#define IND (0) 511#define TAG(x) x 512#include "tnl_dd/t_dd_tritmp.h" 513 514#define IND (INTEL_OFFSET_BIT) 515#define TAG(x) x##_offset 516#include "tnl_dd/t_dd_tritmp.h" 517 518#define IND (INTEL_TWOSIDE_BIT) 519#define TAG(x) x##_twoside 520#include "tnl_dd/t_dd_tritmp.h" 521 522#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT) 523#define TAG(x) x##_twoside_offset 524#include "tnl_dd/t_dd_tritmp.h" 525 526#define IND (INTEL_UNFILLED_BIT) 527#define TAG(x) x##_unfilled 528#include "tnl_dd/t_dd_tritmp.h" 529 530#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT) 531#define TAG(x) x##_offset_unfilled 532#include "tnl_dd/t_dd_tritmp.h" 533 534#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT) 535#define TAG(x) x##_twoside_unfilled 536#include "tnl_dd/t_dd_tritmp.h" 537 538#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT) 539#define TAG(x) x##_twoside_offset_unfilled 540#include "tnl_dd/t_dd_tritmp.h" 541 542#define IND (INTEL_FALLBACK_BIT) 543#define TAG(x) x##_fallback 544#include "tnl_dd/t_dd_tritmp.h" 545 546#define IND (INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT) 547#define TAG(x) x##_offset_fallback 548#include "tnl_dd/t_dd_tritmp.h" 549 550#define IND (INTEL_TWOSIDE_BIT|INTEL_FALLBACK_BIT) 551#define TAG(x) x##_twoside_fallback 552#include "tnl_dd/t_dd_tritmp.h" 553 554#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT) 555#define TAG(x) x##_twoside_offset_fallback 556#include "tnl_dd/t_dd_tritmp.h" 557 558#define IND (INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT) 559#define TAG(x) x##_unfilled_fallback 560#include "tnl_dd/t_dd_tritmp.h" 561 562#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT) 563#define TAG(x) x##_offset_unfilled_fallback 564#include "tnl_dd/t_dd_tritmp.h" 565 566#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT) 567#define TAG(x) x##_twoside_unfilled_fallback 568#include "tnl_dd/t_dd_tritmp.h" 569 570#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT| \ 571 INTEL_FALLBACK_BIT) 572#define TAG(x) x##_twoside_offset_unfilled_fallback 573#include "tnl_dd/t_dd_tritmp.h" 574 575 576static void 577init_rast_tab(void) 578{ 579 init(); 580 init_offset(); 581 init_twoside(); 582 init_twoside_offset(); 583 init_unfilled(); 584 init_offset_unfilled(); 585 init_twoside_unfilled(); 586 init_twoside_offset_unfilled(); 587 init_fallback(); 588 init_offset_fallback(); 589 init_twoside_fallback(); 590 init_twoside_offset_fallback(); 591 init_unfilled_fallback(); 592 init_offset_unfilled_fallback(); 593 init_twoside_unfilled_fallback(); 594 init_twoside_offset_unfilled_fallback(); 595} 596 597 598/*********************************************************************** 599 * Rasterization fallback helpers * 600 ***********************************************************************/ 601 602 603/* This code is hit only when a mix of accelerated and unaccelerated 604 * primitives are being drawn, and only for the unaccelerated 605 * primitives. 606 */ 607static void 608intel_fallback_tri(struct intel_context *intel, 609 intelVertex * v0, intelVertex * v1, intelVertex * v2) 610{ 611 GLcontext *ctx = &intel->ctx; 612 SWvertex v[3]; 613 614 if (0) 615 fprintf(stderr, "\n%s\n", __FUNCTION__); 616 617 INTEL_FIREVERTICES(intel); 618 619 _swsetup_Translate(ctx, v0, &v[0]); 620 _swsetup_Translate(ctx, v1, &v[1]); 621 _swsetup_Translate(ctx, v2, &v[2]); 622 intelSpanRenderStart(ctx); 623 _swrast_Triangle(ctx, &v[0], &v[1], &v[2]); 624 intelSpanRenderFinish(ctx); 625} 626 627 628static void 629intel_fallback_line(struct intel_context *intel, 630 intelVertex * v0, intelVertex * v1) 631{ 632 GLcontext *ctx = &intel->ctx; 633 SWvertex v[2]; 634 635 if (0) 636 fprintf(stderr, "\n%s\n", __FUNCTION__); 637 638 INTEL_FIREVERTICES(intel); 639 640 _swsetup_Translate(ctx, v0, &v[0]); 641 _swsetup_Translate(ctx, v1, &v[1]); 642 intelSpanRenderStart(ctx); 643 _swrast_Line(ctx, &v[0], &v[1]); 644 intelSpanRenderFinish(ctx); 645} 646 647static void 648intel_fallback_point(struct intel_context *intel, 649 intelVertex * v0) 650{ 651 GLcontext *ctx = &intel->ctx; 652 SWvertex v[1]; 653 654 if (0) 655 fprintf(stderr, "\n%s\n", __FUNCTION__); 656 657 INTEL_FIREVERTICES(intel); 658 659 _swsetup_Translate(ctx, v0, &v[0]); 660 intelSpanRenderStart(ctx); 661 _swrast_Point(ctx, &v[0]); 662 intelSpanRenderFinish(ctx); 663} 664 665 666/**********************************************************************/ 667/* Render unclipped begin/end objects */ 668/**********************************************************************/ 669 670#define IND 0 671#define V(x) (intelVertex *)(vertptr + ((x)*vertsize*sizeof(GLuint))) 672#define RENDER_POINTS( start, count ) \ 673 for ( ; start < count ; start++) POINT( V(ELT(start)) ); 674#define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) ) 675#define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) ) 676#define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) ) 677#define INIT(x) intelRenderPrimitive( ctx, x ) 678#undef LOCAL_VARS 679#define LOCAL_VARS \ 680 struct intel_context *intel = intel_context(ctx); \ 681 GLubyte *vertptr = (GLubyte *)intel->verts; \ 682 const GLuint vertsize = intel->vertex_size; \ 683 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ 684 (void) elt; 685#define RESET_STIPPLE 686#define RESET_OCCLUSION 687#define PRESERVE_VB_DEFS 688#define ELT(x) x 689#define TAG(x) intel_##x##_verts 690#include "tnl/t_vb_rendertmp.h" 691#undef ELT 692#undef TAG 693#define TAG(x) intel_##x##_elts 694#define ELT(x) elt[x] 695#include "tnl/t_vb_rendertmp.h" 696 697/**********************************************************************/ 698/* Render clipped primitives */ 699/**********************************************************************/ 700 701 702 703static void 704intelRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n) 705{ 706 struct intel_context *intel = intel_context(ctx); 707 TNLcontext *tnl = TNL_CONTEXT(ctx); 708 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 709 GLuint prim = intel->render_primitive; 710 711 /* Render the new vertices as an unclipped polygon. 712 */ 713 { 714 GLuint *tmp = VB->Elts; 715 VB->Elts = (GLuint *) elts; 716 tnl->Driver.Render.PrimTabElts[GL_POLYGON] (ctx, 0, n, 717 PRIM_BEGIN | PRIM_END); 718 VB->Elts = tmp; 719 } 720 721 /* Restore the render primitive 722 */ 723 if (prim != GL_POLYGON) 724 tnl->Driver.Render.PrimitiveNotify(ctx, prim); 725} 726 727static void 728intelRenderClippedLine(GLcontext * ctx, GLuint ii, GLuint jj) 729{ 730 TNLcontext *tnl = TNL_CONTEXT(ctx); 731 732 tnl->Driver.Render.Line(ctx, ii, jj); 733} 734 735static void 736intelFastRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n) 737{ 738 struct intel_context *intel = intel_context(ctx); 739 const GLuint vertsize = intel->vertex_size; 740 GLuint *vb = intelExtendInlinePrimitive(intel, (n - 2) * 3 * vertsize); 741 GLubyte *vertptr = (GLubyte *) intel->verts; 742 const GLuint *start = (const GLuint *) V(elts[0]); 743 int i, j; 744 745 for (i = 2; i < n; i++) { 746 COPY_DWORDS(j, vb, vertsize, V(elts[i - 1])); 747 COPY_DWORDS(j, vb, vertsize, V(elts[i])); 748 COPY_DWORDS(j, vb, vertsize, start); 749 } 750} 751 752/**********************************************************************/ 753/* Choose render functions */ 754/**********************************************************************/ 755 756 757 758 759#define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN | DD_POINT_SMOOTH | DD_TRI_SMOOTH) 760#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED) 761 762void 763intelChooseRenderState(GLcontext * ctx) 764{ 765 TNLcontext *tnl = TNL_CONTEXT(ctx); 766 struct intel_context *intel = intel_context(ctx); 767 GLuint flags = ctx->_TriangleCaps; 768 const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; 769 GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS)); 770 GLuint index = 0; 771 772 if (INTEL_DEBUG & DEBUG_STATE) 773 fprintf(stderr, "\n%s\n", __FUNCTION__); 774 775 if ((flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) || have_wpos) { 776 777 if (flags & ANY_RASTER_FLAGS) { 778 if (flags & DD_TRI_LIGHT_TWOSIDE) 779 index |= INTEL_TWOSIDE_BIT; 780 if (flags & DD_TRI_OFFSET) 781 index |= INTEL_OFFSET_BIT; 782 if (flags & DD_TRI_UNFILLED) 783 index |= INTEL_UNFILLED_BIT; 784 } 785 786 if (have_wpos) { 787 intel->draw_point = intel_wpos_point; 788 intel->draw_line = intel_wpos_line; 789 intel->draw_tri = intel_wpos_triangle; 790 791 /* Make sure these get called: 792 */ 793 index |= INTEL_FALLBACK_BIT; 794 } 795 else { 796 intel->draw_point = intel_draw_point; 797 intel->draw_line = intel_draw_line; 798 intel->draw_tri = intel_draw_triangle; 799 } 800 801 /* Hook in fallbacks for specific primitives. 802 */ 803 if (flags & ANY_FALLBACK_FLAGS) { 804 if (flags & DD_LINE_STIPPLE) 805 intel->draw_line = intel_fallback_line; 806 807 if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple) 808 intel->draw_tri = intel_fallback_tri; 809 810 if (flags & DD_TRI_SMOOTH) { 811 if (intel->strict_conformance) 812 intel->draw_tri = intel_fallback_tri; 813 } 814 815 if (flags & DD_POINT_ATTEN) { 816 if (0) 817 intel->draw_point = intel_atten_point; 818 else 819 intel->draw_point = intel_fallback_point; 820 } 821 822 if (flags & DD_POINT_SMOOTH) { 823 if (intel->strict_conformance) 824 intel->draw_point = intel_fallback_point; 825 } 826 827 index |= INTEL_FALLBACK_BIT; 828 } 829 } 830 831 if (intel->RenderIndex != index) { 832 intel->RenderIndex = index; 833 834 tnl->Driver.Render.Points = rast_tab[index].points; 835 tnl->Driver.Render.Line = rast_tab[index].line; 836 tnl->Driver.Render.Triangle = rast_tab[index].triangle; 837 tnl->Driver.Render.Quad = rast_tab[index].quad; 838 839 if (index == 0) { 840 tnl->Driver.Render.PrimTabVerts = intel_render_tab_verts; 841 tnl->Driver.Render.PrimTabElts = intel_render_tab_elts; 842 tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ 843 tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly; 844 } 845 else { 846 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; 847 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; 848 tnl->Driver.Render.ClippedLine = intelRenderClippedLine; 849 tnl->Driver.Render.ClippedPolygon = intelRenderClippedPoly; 850 } 851 } 852} 853 854static const GLenum reduced_prim[GL_POLYGON + 1] = { 855 GL_POINTS, 856 GL_LINES, 857 GL_LINES, 858 GL_LINES, 859 GL_TRIANGLES, 860 GL_TRIANGLES, 861 GL_TRIANGLES, 862 GL_TRIANGLES, 863 GL_TRIANGLES, 864 GL_TRIANGLES 865}; 866 867 868/**********************************************************************/ 869/* High level hooks for t_vb_render.c */ 870/**********************************************************************/ 871 872 873 874 875static void 876intelRunPipeline(GLcontext * ctx) 877{ 878 struct intel_context *intel = intel_context(ctx); 879 880 _mesa_lock_context_textures(ctx); 881 882 if (ctx->NewState) 883 _mesa_update_state_locked(ctx); 884 885 if (intel->NewGLState) { 886 if (intel->NewGLState & _NEW_TEXTURE) { 887 intel->vtbl.update_texture_state(intel); 888 } 889 890 if (!intel->Fallback) { 891 if (intel->NewGLState & _INTEL_NEW_RENDERSTATE) 892 intelChooseRenderState(ctx); 893 } 894 895 intel->NewGLState = 0; 896 } 897 898 _tnl_run_pipeline(ctx); 899 900 _mesa_unlock_context_textures(ctx); 901} 902 903static void 904intelRenderStart(GLcontext * ctx) 905{ 906 struct intel_context *intel = intel_context(ctx); 907 908 intel->vtbl.render_start(intel_context(ctx)); 909 intel->vtbl.emit_state(intel); 910} 911 912static void 913intelRenderFinish(GLcontext * ctx) 914{ 915 struct intel_context *intel = intel_context(ctx); 916 917 if (intel->RenderIndex & INTEL_FALLBACK_BIT) 918 _swrast_flush(ctx); 919 920 INTEL_FIREVERTICES(intel); 921} 922 923 924 925 926 /* System to flush dma and emit state changes based on the rasterized 927 * primitive. 928 */ 929static void 930intelRasterPrimitive(GLcontext * ctx, GLenum rprim, GLuint hwprim) 931{ 932 struct intel_context *intel = intel_context(ctx); 933 934 if (0) 935 fprintf(stderr, "%s %s %x\n", __FUNCTION__, 936 _mesa_lookup_enum_by_nr(rprim), hwprim); 937 938 intel->vtbl.reduced_primitive_state(intel, rprim); 939 940 /* Start a new primitive. Arrange to have it flushed later on. 941 */ 942 if (hwprim != intel->prim.primitive) { 943 INTEL_FIREVERTICES(intel); 944 945 intelStartInlinePrimitive(intel, hwprim, INTEL_BATCH_CLIPRECTS); 946 } 947} 948 949 950 /* 951 */ 952static void 953intelRenderPrimitive(GLcontext * ctx, GLenum prim) 954{ 955 struct intel_context *intel = intel_context(ctx); 956 957 if (0) 958 fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); 959 960 /* Let some clipping routines know which primitive they're dealing 961 * with. 962 */ 963 intel->render_primitive = prim; 964 965 /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled 966 * triangles. The rasterized primitive will always be reset by 967 * lower level functions in that case, potentially pingponging the 968 * state: 969 */ 970 if (reduced_prim[prim] == GL_TRIANGLES && 971 (ctx->_TriangleCaps & DD_TRI_UNFILLED)) 972 return; 973 974 /* Set some primitive-dependent state and Start? a new primitive. 975 */ 976 intelRasterPrimitive(ctx, reduced_prim[prim], hw_prim[prim]); 977} 978 979 980 /**********************************************************************/ 981 /* Transition to/from hardware rasterization. */ 982 /**********************************************************************/ 983 984static char *fallbackStrings[] = { 985 [0] = "Draw buffer", 986 [1] = "Read buffer", 987 [2] = "Depth buffer", 988 [3] = "Stencil buffer", 989 [4] = "User disable", 990 [5] = "Render mode", 991 992 [12] = "Texture", 993 [13] = "Color mask", 994 [14] = "Stencil", 995 [15] = "Stipple", 996 [16] = "Program", 997 [17] = "Logic op", 998 [18] = "Smooth polygon", 999 [19] = "Smooth point", 1000}; 1001 1002 1003static char * 1004getFallbackString(GLuint bit) 1005{ 1006 int i = 0; 1007 while (bit > 1) { 1008 i++; 1009 bit >>= 1; 1010 } 1011 return fallbackStrings[i]; 1012} 1013 1014 1015 1016void 1017intelFallback(struct intel_context *intel, GLuint bit, GLboolean mode) 1018{ 1019 GLcontext *ctx = &intel->ctx; 1020 TNLcontext *tnl = TNL_CONTEXT(ctx); 1021 GLuint oldfallback = intel->Fallback; 1022 1023 if (mode) { 1024 intel->Fallback |= bit; 1025 if (oldfallback == 0) { 1026 intelFlush(ctx); 1027 if (INTEL_DEBUG & DEBUG_FALLBACKS) 1028 fprintf(stderr, "ENTER FALLBACK %x: %s\n", 1029 bit, getFallbackString(bit)); 1030 _swsetup_Wakeup(ctx); 1031 intel->RenderIndex = ~0; 1032 } 1033 } 1034 else { 1035 intel->Fallback &= ~bit; 1036 if (oldfallback == bit) { 1037 _swrast_flush(ctx); 1038 if (INTEL_DEBUG & DEBUG_FALLBACKS) 1039 fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString(bit)); 1040 tnl->Driver.Render.Start = intelRenderStart; 1041 tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; 1042 tnl->Driver.Render.Finish = intelRenderFinish; 1043 tnl->Driver.Render.BuildVertices = _tnl_build_vertices; 1044 tnl->Driver.Render.CopyPV = _tnl_copy_pv; 1045 tnl->Driver.Render.Interp = _tnl_interp; 1046 1047 _tnl_invalidate_vertex_state(ctx, ~0); 1048 _tnl_invalidate_vertices(ctx, ~0); 1049 _tnl_install_attrs(ctx, 1050 intel->vertex_attrs, 1051 intel->vertex_attr_count, 1052 intel->ViewportMatrix.m, 0); 1053 1054 intel->NewGLState |= _INTEL_NEW_RENDERSTATE; 1055 } 1056 } 1057} 1058 1059union fi 1060{ 1061 GLfloat f; 1062 GLint i; 1063}; 1064 1065 1066/**********************************************************************/ 1067/* Used only with the metaops callbacks. */ 1068/**********************************************************************/ 1069static void 1070intel_meta_draw_poly(struct intel_context *intel, 1071 GLuint n, 1072 GLfloat xy[][2], 1073 GLfloat z, GLuint color, GLfloat tex[][2]) 1074{ 1075 union fi *vb; 1076 GLint i; 1077 GLboolean was_locked = intel->locked; 1078 1079 if (!was_locked) 1080 LOCK_HARDWARE(intel); 1081 1082 /* All 3d primitives should be emitted with INTEL_BATCH_CLIPRECTS, 1083 * otherwise the drawing origin (DR4) might not be set correctly. 1084 */ 1085 intelStartInlinePrimitive(intel, PRIM3D_TRIFAN, INTEL_BATCH_CLIPRECTS); 1086 vb = (union fi *) intelExtendInlinePrimitive(intel, n * 6); 1087 1088 for (i = 0; i < n; i++) { 1089 vb[0].f = xy[i][0]; 1090 vb[1].f = xy[i][1]; 1091 vb[2].f = z; 1092 vb[3].i = color; 1093 vb[4].f = tex[i][0]; 1094 vb[5].f = tex[i][1]; 1095 vb += 6; 1096 } 1097 1098 INTEL_FIREVERTICES(intel); 1099 1100 if (!was_locked) 1101 UNLOCK_HARDWARE(intel); 1102} 1103 1104static void 1105intel_meta_draw_quad(struct intel_context *intel, 1106 GLfloat x0, GLfloat x1, 1107 GLfloat y0, GLfloat y1, 1108 GLfloat z, 1109 GLuint color, 1110 GLfloat s0, GLfloat s1, GLfloat t0, GLfloat t1) 1111{ 1112 GLfloat xy[4][2]; 1113 GLfloat tex[4][2]; 1114 1115 xy[0][0] = x0; 1116 xy[0][1] = y0; 1117 xy[1][0] = x1; 1118 xy[1][1] = y0; 1119 xy[2][0] = x1; 1120 xy[2][1] = y1; 1121 xy[3][0] = x0; 1122 xy[3][1] = y1; 1123 1124 tex[0][0] = s0; 1125 tex[0][1] = t0; 1126 tex[1][0] = s1; 1127 tex[1][1] = t0; 1128 tex[2][0] = s1; 1129 tex[2][1] = t1; 1130 tex[3][0] = s0; 1131 tex[3][1] = t1; 1132 1133 intel_meta_draw_poly(intel, 4, xy, z, color, tex); 1134} 1135 1136 1137 1138/**********************************************************************/ 1139/* Initialization. */ 1140/**********************************************************************/ 1141 1142 1143void 1144intelInitTriFuncs(GLcontext * ctx) 1145{ 1146 struct intel_context *intel = intel_context(ctx); 1147 TNLcontext *tnl = TNL_CONTEXT(ctx); 1148 static int firsttime = 1; 1149 1150 if (firsttime) { 1151 init_rast_tab(); 1152 firsttime = 0; 1153 } 1154 1155 tnl->Driver.RunPipeline = intelRunPipeline; 1156 tnl->Driver.Render.Start = intelRenderStart; 1157 tnl->Driver.Render.Finish = intelRenderFinish; 1158 tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; 1159 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; 1160 tnl->Driver.Render.BuildVertices = _tnl_build_vertices; 1161 tnl->Driver.Render.CopyPV = _tnl_copy_pv; 1162 tnl->Driver.Render.Interp = _tnl_interp; 1163 1164 intel->vtbl.meta_draw_quad = intel_meta_draw_quad; 1165} 1166