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