intel_tris.c revision 5203b7227ccb6b618fa42f08434d4a3cf123dca2
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/** @file intel_tris.c 29 * 30 * This file contains functions for managing the vertex buffer and emitting 31 * primitives into it. 32 */ 33 34#include "main/glheader.h" 35#include "main/context.h" 36#include "main/macros.h" 37#include "main/enums.h" 38#include "main/texobj.h" 39#include "main/state.h" 40#include "main/dd.h" 41 42#include "swrast/swrast.h" 43#include "swrast_setup/swrast_setup.h" 44#include "tnl/t_context.h" 45#include "tnl/t_pipeline.h" 46#include "tnl/t_vertex.h" 47 48#include "intel_screen.h" 49#include "intel_context.h" 50#include "intel_tris.h" 51#include "intel_batchbuffer.h" 52#include "intel_buffers.h" 53#include "intel_reg.h" 54#include "intel_span.h" 55#include "intel_tex.h" 56#include "intel_chipset.h" 57#include "i830_context.h" 58#include "i830_reg.h" 59 60static void intelRenderPrimitive(GLcontext * ctx, GLenum prim); 61static void intelRasterPrimitive(GLcontext * ctx, GLenum rprim, 62 GLuint hwprim); 63 64static void 65intel_flush_inline_primitive(struct intel_context *intel) 66{ 67 GLuint used = intel->batch->ptr - intel->prim.start_ptr; 68 69 assert(intel->prim.primitive != ~0); 70 71/* _mesa_printf("/\n"); */ 72 73 if (used < 8) 74 goto do_discard; 75 76 *(int *) intel->prim.start_ptr = (_3DPRIMITIVE | 77 intel->prim.primitive | (used / 4 - 2)); 78 79 goto finished; 80 81 do_discard: 82 intel->batch->ptr -= used; 83 84 finished: 85 intel->prim.primitive = ~0; 86 intel->prim.start_ptr = 0; 87 intel->prim.flush = 0; 88} 89 90static void intel_start_inline(struct intel_context *intel, uint32_t prim) 91{ 92 BATCH_LOCALS; 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); 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/* _mesa_printf(">"); */ 117} 118 119static void intel_wrap_inline(struct intel_context *intel) 120{ 121 GLuint prim = intel->prim.primitive; 122 123 intel_flush_inline_primitive(intel); 124 intel_batchbuffer_flush(intel->batch); 125 intel_start_inline(intel, prim); /* ??? */ 126} 127 128static GLuint *intel_extend_inline(struct intel_context *intel, GLuint dwords) 129{ 130 GLuint sz = dwords * sizeof(GLuint); 131 GLuint *ptr; 132 133 assert(intel->prim.flush == intel_flush_inline_primitive); 134 135 if (intel_batchbuffer_space(intel->batch) < sz) 136 intel_wrap_inline(intel); 137 138/* _mesa_printf("."); */ 139 140 intel->vtbl.assert_not_dirty(intel); 141 142 ptr = (GLuint *) intel->batch->ptr; 143 intel->batch->ptr += sz; 144 145 return ptr; 146} 147 148/** Sets the primitive type for a primitive sequence, flushing as needed. */ 149void intel_set_prim(struct intel_context *intel, uint32_t prim) 150{ 151 /* if we have no VBOs */ 152 153 if (intel->intelScreen->no_vbo) { 154 intel_start_inline(intel, prim); 155 return; 156 } 157 if (prim != intel->prim.primitive) { 158 INTEL_FIREVERTICES(intel); 159 intel->prim.primitive = prim; 160 } 161} 162 163/** Returns mapped VB space for the given number of vertices */ 164uint32_t *intel_get_prim_space(struct intel_context *intel, unsigned int count) 165{ 166 uint32_t *addr; 167 168 if (intel->intelScreen->no_vbo) { 169 return intel_extend_inline(intel, count * intel->vertex_size); 170 } 171 172 /* Check for space in the existing VB */ 173 if (intel->prim.vb_bo == NULL || 174 (intel->prim.current_offset + 175 count * intel->vertex_size * 4) > INTEL_VB_SIZE || 176 (intel->prim.count + count) >= (1 << 16)) { 177 /* Flush existing prim if any */ 178 INTEL_FIREVERTICES(intel); 179 180 intel_finish_vb(intel); 181 182 /* Start a new VB */ 183 if (intel->prim.vb == NULL) 184 intel->prim.vb = malloc(INTEL_VB_SIZE); 185 intel->prim.vb_bo = dri_bo_alloc(intel->bufmgr, "vb", 186 INTEL_VB_SIZE, 4); 187 intel->prim.start_offset = 0; 188 intel->prim.current_offset = 0; 189 } 190 191 intel->prim.flush = intel_flush_prim; 192 193 addr = (uint32_t *)(intel->prim.vb + intel->prim.current_offset); 194 intel->prim.current_offset += intel->vertex_size * 4 * count; 195 intel->prim.count += count; 196 197 return addr; 198} 199 200/** Dispatches the accumulated primitive to the batchbuffer. */ 201void intel_flush_prim(struct intel_context *intel) 202{ 203 dri_bo *aper_array[2]; 204 dri_bo *vb_bo; 205 unsigned int offset, count; 206 BATCH_LOCALS; 207 208 /* Must be called after an intel_start_prim. */ 209 assert(intel->prim.primitive != ~0); 210 211 if (intel->prim.count == 0) 212 return; 213 214 /* Clear the current prims out of the context state so that a batch flush 215 * flush triggered by emit_state doesn't loop back to flush_prim again. 216 */ 217 vb_bo = intel->prim.vb_bo; 218 dri_bo_reference(vb_bo); 219 count = intel->prim.count; 220 intel->prim.count = 0; 221 offset = intel->prim.start_offset; 222 intel->prim.start_offset = intel->prim.current_offset; 223 if (!intel->gen >= 3) 224 intel->prim.start_offset = ALIGN(intel->prim.start_offset, 128); 225 intel->prim.flush = NULL; 226 227 intel->vtbl.emit_state(intel); 228 229 aper_array[0] = intel->batch->buf; 230 aper_array[1] = vb_bo; 231 if (dri_bufmgr_check_aperture_space(aper_array, 2)) { 232 intel_batchbuffer_flush(intel->batch); 233 intel->vtbl.emit_state(intel); 234 } 235 236 /* Ensure that we don't start a new batch for the following emit, which 237 * depends on the state just emitted. emit_state should be making sure we 238 * have the space for this. 239 */ 240 intel->no_batch_wrap = GL_TRUE; 241 242 /* Check that we actually emitted the state into this batch, using the 243 * UPLOAD_CTX bit as the signal. 244 */ 245 assert((intel->batch->dirty_state & (1<<1)) == 0); 246 247#if 0 248 printf("emitting %d..%d=%d vertices size %d\n", offset, 249 intel->prim.current_offset, count, 250 intel->vertex_size * 4); 251#endif 252 253 if (intel->gen >= 3) { 254 BEGIN_BATCH(5); 255 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 256 I1_LOAD_S(0) | I1_LOAD_S(1) | 1); 257 assert((offset & !S0_VB_OFFSET_MASK) == 0); 258 OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, offset); 259 OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) | 260 (intel->vertex_size << S1_VERTEX_PITCH_SHIFT)); 261 262 OUT_BATCH(_3DPRIMITIVE | 263 PRIM_INDIRECT | 264 PRIM_INDIRECT_SEQUENTIAL | 265 intel->prim.primitive | 266 count); 267 OUT_BATCH(0); /* Beginning vertex index */ 268 ADVANCE_BATCH(); 269 } else { 270 struct i830_context *i830 = i830_context(&intel->ctx); 271 272 BEGIN_BATCH(5); 273 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 274 I1_LOAD_S(0) | I1_LOAD_S(2) | 1); 275 /* S0 */ 276 assert((offset & !S0_VB_OFFSET_MASK_830) == 0); 277 OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, 278 offset | (intel->vertex_size << S0_VB_PITCH_SHIFT_830) | 279 S0_VB_ENABLE_830); 280 /* S2 281 * This is somewhat unfortunate -- VB width is tied up with 282 * vertex format data that we've already uploaded through 283 * _3DSTATE_VFT[01]_CMD. We may want to replace emits of VFT state with 284 * STATE_IMMEDIATE_1 like this to avoid duplication. 285 */ 286 OUT_BATCH((i830->state.Ctx[I830_CTXREG_VF] & VFT0_TEX_COUNT_MASK) >> 287 VFT0_TEX_COUNT_SHIFT << S2_TEX_COUNT_SHIFT_830 | 288 (i830->state.Ctx[I830_CTXREG_VF2] << 16) | 289 intel->vertex_size << S2_VERTEX_0_WIDTH_SHIFT_830); 290 291 OUT_BATCH(_3DPRIMITIVE | 292 PRIM_INDIRECT | 293 PRIM_INDIRECT_SEQUENTIAL | 294 intel->prim.primitive | 295 count); 296 OUT_BATCH(0); /* Beginning vertex index */ 297 ADVANCE_BATCH(); 298 } 299 300 intel->no_batch_wrap = GL_FALSE; 301 302 dri_bo_unreference(vb_bo); 303} 304 305/** 306 * Uploads the locally-accumulated VB into the buffer object. 307 * 308 * This avoids us thrashing the cachelines in and out as the buffer gets 309 * filled, dispatched, then reused as the hardware completes rendering from it, 310 * and also lets us clflush less if we dispatch with a partially-filled VB. 311 * 312 * This is called normally from get_space when we're finishing a BO, but also 313 * at batch flush time so that we don't try accessing the contents of a 314 * just-dispatched buffer. 315 */ 316void intel_finish_vb(struct intel_context *intel) 317{ 318 if (intel->prim.vb_bo == NULL) 319 return; 320 321 dri_bo_subdata(intel->prim.vb_bo, 0, intel->prim.start_offset, 322 intel->prim.vb); 323 dri_bo_unreference(intel->prim.vb_bo); 324 intel->prim.vb_bo = NULL; 325} 326 327/*********************************************************************** 328 * Emit primitives as inline vertices * 329 ***********************************************************************/ 330 331#ifdef __i386__ 332#define COPY_DWORDS( j, vb, vertsize, v ) \ 333do { \ 334 int __tmp; \ 335 __asm__ __volatile__( "rep ; movsl" \ 336 : "=%c" (j), "=D" (vb), "=S" (__tmp) \ 337 : "0" (vertsize), \ 338 "D" ((long)vb), \ 339 "S" ((long)v) ); \ 340} while (0) 341#else 342#define COPY_DWORDS( j, vb, vertsize, v ) \ 343do { \ 344 for ( j = 0 ; j < vertsize ; j++ ) { \ 345 vb[j] = ((GLuint *)v)[j]; \ 346 } \ 347 vb += vertsize; \ 348} while (0) 349#endif 350 351static void 352intel_draw_quad(struct intel_context *intel, 353 intelVertexPtr v0, 354 intelVertexPtr v1, intelVertexPtr v2, intelVertexPtr v3) 355{ 356 GLuint vertsize = intel->vertex_size; 357 GLuint *vb = intel_get_prim_space(intel, 6); 358 int j; 359 360 COPY_DWORDS(j, vb, vertsize, v0); 361 COPY_DWORDS(j, vb, vertsize, v1); 362 363 /* If smooth shading, draw like a trifan which gives better 364 * rasterization. Otherwise draw as two triangles with provoking 365 * vertex in third position as required for flat shading. 366 */ 367 if (intel->ctx.Light.ShadeModel == GL_FLAT) { 368 COPY_DWORDS(j, vb, vertsize, v3); 369 COPY_DWORDS(j, vb, vertsize, v1); 370 } 371 else { 372 COPY_DWORDS(j, vb, vertsize, v2); 373 COPY_DWORDS(j, vb, vertsize, v0); 374 } 375 376 COPY_DWORDS(j, vb, vertsize, v2); 377 COPY_DWORDS(j, vb, vertsize, v3); 378} 379 380static void 381intel_draw_triangle(struct intel_context *intel, 382 intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2) 383{ 384 GLuint vertsize = intel->vertex_size; 385 GLuint *vb = intel_get_prim_space(intel, 3); 386 int j; 387 388 COPY_DWORDS(j, vb, vertsize, v0); 389 COPY_DWORDS(j, vb, vertsize, v1); 390 COPY_DWORDS(j, vb, vertsize, v2); 391} 392 393 394static void 395intel_draw_line(struct intel_context *intel, 396 intelVertexPtr v0, intelVertexPtr v1) 397{ 398 GLuint vertsize = intel->vertex_size; 399 GLuint *vb = intel_get_prim_space(intel, 2); 400 int j; 401 402 COPY_DWORDS(j, vb, vertsize, v0); 403 COPY_DWORDS(j, vb, vertsize, v1); 404} 405 406 407static void 408intel_draw_point(struct intel_context *intel, intelVertexPtr v0) 409{ 410 GLuint vertsize = intel->vertex_size; 411 GLuint *vb = intel_get_prim_space(intel, 1); 412 int j; 413 414 /* Adjust for sub pixel position -- still required for conform. */ 415 *(float *) &vb[0] = v0->v.x; 416 *(float *) &vb[1] = v0->v.y; 417 for (j = 2; j < vertsize; j++) 418 vb[j] = v0->ui[j]; 419} 420 421 422 423/*********************************************************************** 424 * Fixup for ARB_point_parameters * 425 ***********************************************************************/ 426 427/* Currently not working - VERT_ATTRIB_POINTSIZE isn't correctly 428 * represented in the fragment program InputsRead field. 429 */ 430static void 431intel_atten_point(struct intel_context *intel, intelVertexPtr v0) 432{ 433 GLcontext *ctx = &intel->ctx; 434 GLfloat psz[4], col[4], restore_psz, restore_alpha; 435 436 _tnl_get_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz); 437 _tnl_get_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col); 438 439 restore_psz = psz[0]; 440 restore_alpha = col[3]; 441 442 if (psz[0] >= ctx->Point.Threshold) { 443 psz[0] = MIN2(psz[0], ctx->Point.MaxSize); 444 } 445 else { 446 GLfloat dsize = psz[0] / ctx->Point.Threshold; 447 psz[0] = MAX2(ctx->Point.Threshold, ctx->Point.MinSize); 448 col[3] *= dsize * dsize; 449 } 450 451 if (psz[0] < 1.0) 452 psz[0] = 1.0; 453 454 if (restore_psz != psz[0] || restore_alpha != col[3]) { 455 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz); 456 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col); 457 458 intel_draw_point(intel, v0); 459 460 psz[0] = restore_psz; 461 col[3] = restore_alpha; 462 463 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz); 464 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col); 465 } 466 else 467 intel_draw_point(intel, v0); 468} 469 470 471 472 473 474/*********************************************************************** 475 * Fixup for I915 WPOS texture coordinate * 476 ***********************************************************************/ 477 478 479 480static void 481intel_wpos_triangle(struct intel_context *intel, 482 intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2) 483{ 484 GLuint offset = intel->wpos_offset; 485 GLuint size = intel->wpos_size; 486 GLfloat *v0_wpos = (GLfloat *)((char *)v0 + offset); 487 GLfloat *v1_wpos = (GLfloat *)((char *)v1 + offset); 488 GLfloat *v2_wpos = (GLfloat *)((char *)v2 + offset); 489 490 __memcpy(v0_wpos, v0, size); 491 __memcpy(v1_wpos, v1, size); 492 __memcpy(v2_wpos, v2, size); 493 494 v0_wpos[1] = -v0_wpos[1] + intel->driDrawable->h; 495 v1_wpos[1] = -v1_wpos[1] + intel->driDrawable->h; 496 v2_wpos[1] = -v2_wpos[1] + intel->driDrawable->h; 497 498 499 intel_draw_triangle(intel, v0, v1, v2); 500} 501 502 503static void 504intel_wpos_line(struct intel_context *intel, 505 intelVertexPtr v0, intelVertexPtr v1) 506{ 507 GLuint offset = intel->wpos_offset; 508 GLuint size = intel->wpos_size; 509 GLfloat *v0_wpos = (GLfloat *)((char *)v0 + offset); 510 GLfloat *v1_wpos = (GLfloat *)((char *)v1 + offset); 511 512 __memcpy(v0_wpos, v0, size); 513 __memcpy(v1_wpos, v1, size); 514 515 v0_wpos[1] = -v0_wpos[1] + intel->driDrawable->h; 516 v1_wpos[1] = -v1_wpos[1] + intel->driDrawable->h; 517 518 intel_draw_line(intel, v0, v1); 519} 520 521 522static void 523intel_wpos_point(struct intel_context *intel, intelVertexPtr v0) 524{ 525 GLuint offset = intel->wpos_offset; 526 GLuint size = intel->wpos_size; 527 GLfloat *v0_wpos = (GLfloat *)((char *)v0 + offset); 528 529 __memcpy(v0_wpos, v0, size); 530 v0_wpos[1] = -v0_wpos[1] + intel->driDrawable->h; 531 532 intel_draw_point(intel, v0); 533} 534 535 536 537 538 539 540/*********************************************************************** 541 * Macros for t_dd_tritmp.h to draw basic primitives * 542 ***********************************************************************/ 543 544#define TRI( a, b, c ) \ 545do { \ 546 if (DO_FALLBACK) \ 547 intel->draw_tri( intel, a, b, c ); \ 548 else \ 549 intel_draw_triangle( intel, a, b, c ); \ 550} while (0) 551 552#define QUAD( a, b, c, d ) \ 553do { \ 554 if (DO_FALLBACK) { \ 555 intel->draw_tri( intel, a, b, d ); \ 556 intel->draw_tri( intel, b, c, d ); \ 557 } else \ 558 intel_draw_quad( intel, a, b, c, d ); \ 559} while (0) 560 561#define LINE( v0, v1 ) \ 562do { \ 563 if (DO_FALLBACK) \ 564 intel->draw_line( intel, v0, v1 ); \ 565 else \ 566 intel_draw_line( intel, v0, v1 ); \ 567} while (0) 568 569#define POINT( v0 ) \ 570do { \ 571 if (DO_FALLBACK) \ 572 intel->draw_point( intel, v0 ); \ 573 else \ 574 intel_draw_point( intel, v0 ); \ 575} while (0) 576 577 578/*********************************************************************** 579 * Build render functions from dd templates * 580 ***********************************************************************/ 581 582#define INTEL_OFFSET_BIT 0x01 583#define INTEL_TWOSIDE_BIT 0x02 584#define INTEL_UNFILLED_BIT 0x04 585#define INTEL_FALLBACK_BIT 0x08 586#define INTEL_MAX_TRIFUNC 0x10 587 588 589static struct 590{ 591 tnl_points_func points; 592 tnl_line_func line; 593 tnl_triangle_func triangle; 594 tnl_quad_func quad; 595} rast_tab[INTEL_MAX_TRIFUNC]; 596 597 598#define DO_FALLBACK (IND & INTEL_FALLBACK_BIT) 599#define DO_OFFSET (IND & INTEL_OFFSET_BIT) 600#define DO_UNFILLED (IND & INTEL_UNFILLED_BIT) 601#define DO_TWOSIDE (IND & INTEL_TWOSIDE_BIT) 602#define DO_FLAT 0 603#define DO_TRI 1 604#define DO_QUAD 1 605#define DO_LINE 1 606#define DO_POINTS 1 607#define DO_FULL_QUAD 1 608 609#define HAVE_RGBA 1 610#define HAVE_SPEC 1 611#define HAVE_BACK_COLORS 0 612#define HAVE_HW_FLATSHADE 1 613#define VERTEX intelVertex 614#define TAB rast_tab 615 616/* Only used to pull back colors into vertices (ie, we know color is 617 * floating point). 618 */ 619#define INTEL_COLOR( dst, src ) \ 620do { \ 621 UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \ 622 UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \ 623 UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \ 624 UNCLAMPED_FLOAT_TO_UBYTE((dst)[3], (src)[3]); \ 625} while (0) 626 627#define INTEL_SPEC( dst, src ) \ 628do { \ 629 UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \ 630 UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \ 631 UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \ 632} while (0) 633 634 635#define DEPTH_SCALE intel->polygon_offset_scale 636#define UNFILLED_TRI unfilled_tri 637#define UNFILLED_QUAD unfilled_quad 638#define VERT_X(_v) _v->v.x 639#define VERT_Y(_v) _v->v.y 640#define VERT_Z(_v) _v->v.z 641#define AREA_IS_CCW( a ) (a > 0) 642#define GET_VERTEX(e) (intel->verts + (e * intel->vertex_size * sizeof(GLuint))) 643 644#define VERT_SET_RGBA( v, c ) if (coloroffset) INTEL_COLOR( v->ub4[coloroffset], c ) 645#define VERT_COPY_RGBA( v0, v1 ) if (coloroffset) v0->ui[coloroffset] = v1->ui[coloroffset] 646#define VERT_SAVE_RGBA( idx ) if (coloroffset) color[idx] = v[idx]->ui[coloroffset] 647#define VERT_RESTORE_RGBA( idx ) if (coloroffset) v[idx]->ui[coloroffset] = color[idx] 648 649#define VERT_SET_SPEC( v, c ) if (specoffset) INTEL_SPEC( v->ub4[specoffset], c ) 650#define VERT_COPY_SPEC( v0, v1 ) if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset]) 651#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset] 652#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] 653 654#define LOCAL_VARS(n) \ 655 struct intel_context *intel = intel_context(ctx); \ 656 GLuint color[n] = { 0, }, spec[n] = { 0, }; \ 657 GLuint coloroffset = intel->coloroffset; \ 658 GLboolean specoffset = intel->specoffset; \ 659 (void) color; (void) spec; (void) coloroffset; (void) specoffset; 660 661 662/*********************************************************************** 663 * Helpers for rendering unfilled primitives * 664 ***********************************************************************/ 665 666static const GLuint hw_prim[GL_POLYGON + 1] = { 667 PRIM3D_POINTLIST, 668 PRIM3D_LINELIST, 669 PRIM3D_LINELIST, 670 PRIM3D_LINELIST, 671 PRIM3D_TRILIST, 672 PRIM3D_TRILIST, 673 PRIM3D_TRILIST, 674 PRIM3D_TRILIST, 675 PRIM3D_TRILIST, 676 PRIM3D_TRILIST 677}; 678 679#define RASTERIZE(x) intelRasterPrimitive( ctx, x, hw_prim[x] ) 680#define RENDER_PRIMITIVE intel->render_primitive 681#define TAG(x) x 682#define IND INTEL_FALLBACK_BIT 683#include "tnl_dd/t_dd_unfilled.h" 684#undef IND 685 686/*********************************************************************** 687 * Generate GL render functions * 688 ***********************************************************************/ 689 690#define IND (0) 691#define TAG(x) x 692#include "tnl_dd/t_dd_tritmp.h" 693 694#define IND (INTEL_OFFSET_BIT) 695#define TAG(x) x##_offset 696#include "tnl_dd/t_dd_tritmp.h" 697 698#define IND (INTEL_TWOSIDE_BIT) 699#define TAG(x) x##_twoside 700#include "tnl_dd/t_dd_tritmp.h" 701 702#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT) 703#define TAG(x) x##_twoside_offset 704#include "tnl_dd/t_dd_tritmp.h" 705 706#define IND (INTEL_UNFILLED_BIT) 707#define TAG(x) x##_unfilled 708#include "tnl_dd/t_dd_tritmp.h" 709 710#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT) 711#define TAG(x) x##_offset_unfilled 712#include "tnl_dd/t_dd_tritmp.h" 713 714#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT) 715#define TAG(x) x##_twoside_unfilled 716#include "tnl_dd/t_dd_tritmp.h" 717 718#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT) 719#define TAG(x) x##_twoside_offset_unfilled 720#include "tnl_dd/t_dd_tritmp.h" 721 722#define IND (INTEL_FALLBACK_BIT) 723#define TAG(x) x##_fallback 724#include "tnl_dd/t_dd_tritmp.h" 725 726#define IND (INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT) 727#define TAG(x) x##_offset_fallback 728#include "tnl_dd/t_dd_tritmp.h" 729 730#define IND (INTEL_TWOSIDE_BIT|INTEL_FALLBACK_BIT) 731#define TAG(x) x##_twoside_fallback 732#include "tnl_dd/t_dd_tritmp.h" 733 734#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT) 735#define TAG(x) x##_twoside_offset_fallback 736#include "tnl_dd/t_dd_tritmp.h" 737 738#define IND (INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT) 739#define TAG(x) x##_unfilled_fallback 740#include "tnl_dd/t_dd_tritmp.h" 741 742#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT) 743#define TAG(x) x##_offset_unfilled_fallback 744#include "tnl_dd/t_dd_tritmp.h" 745 746#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT) 747#define TAG(x) x##_twoside_unfilled_fallback 748#include "tnl_dd/t_dd_tritmp.h" 749 750#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT| \ 751 INTEL_FALLBACK_BIT) 752#define TAG(x) x##_twoside_offset_unfilled_fallback 753#include "tnl_dd/t_dd_tritmp.h" 754 755 756static void 757init_rast_tab(void) 758{ 759 init(); 760 init_offset(); 761 init_twoside(); 762 init_twoside_offset(); 763 init_unfilled(); 764 init_offset_unfilled(); 765 init_twoside_unfilled(); 766 init_twoside_offset_unfilled(); 767 init_fallback(); 768 init_offset_fallback(); 769 init_twoside_fallback(); 770 init_twoside_offset_fallback(); 771 init_unfilled_fallback(); 772 init_offset_unfilled_fallback(); 773 init_twoside_unfilled_fallback(); 774 init_twoside_offset_unfilled_fallback(); 775} 776 777 778/*********************************************************************** 779 * Rasterization fallback helpers * 780 ***********************************************************************/ 781 782 783/* This code is hit only when a mix of accelerated and unaccelerated 784 * primitives are being drawn, and only for the unaccelerated 785 * primitives. 786 */ 787static void 788intel_fallback_tri(struct intel_context *intel, 789 intelVertex * v0, intelVertex * v1, intelVertex * v2) 790{ 791 GLcontext *ctx = &intel->ctx; 792 SWvertex v[3]; 793 794 if (0) 795 fprintf(stderr, "\n%s\n", __FUNCTION__); 796 797 INTEL_FIREVERTICES(intel); 798 799 _swsetup_Translate(ctx, v0, &v[0]); 800 _swsetup_Translate(ctx, v1, &v[1]); 801 _swsetup_Translate(ctx, v2, &v[2]); 802 intelSpanRenderStart(ctx); 803 _swrast_Triangle(ctx, &v[0], &v[1], &v[2]); 804 intelSpanRenderFinish(ctx); 805} 806 807 808static void 809intel_fallback_line(struct intel_context *intel, 810 intelVertex * v0, intelVertex * v1) 811{ 812 GLcontext *ctx = &intel->ctx; 813 SWvertex v[2]; 814 815 if (0) 816 fprintf(stderr, "\n%s\n", __FUNCTION__); 817 818 INTEL_FIREVERTICES(intel); 819 820 _swsetup_Translate(ctx, v0, &v[0]); 821 _swsetup_Translate(ctx, v1, &v[1]); 822 intelSpanRenderStart(ctx); 823 _swrast_Line(ctx, &v[0], &v[1]); 824 intelSpanRenderFinish(ctx); 825} 826 827static void 828intel_fallback_point(struct intel_context *intel, 829 intelVertex * v0) 830{ 831 GLcontext *ctx = &intel->ctx; 832 SWvertex v[1]; 833 834 if (0) 835 fprintf(stderr, "\n%s\n", __FUNCTION__); 836 837 INTEL_FIREVERTICES(intel); 838 839 _swsetup_Translate(ctx, v0, &v[0]); 840 intelSpanRenderStart(ctx); 841 _swrast_Point(ctx, &v[0]); 842 intelSpanRenderFinish(ctx); 843} 844 845 846/**********************************************************************/ 847/* Render unclipped begin/end objects */ 848/**********************************************************************/ 849 850#define IND 0 851#define V(x) (intelVertex *)(vertptr + ((x)*vertsize*sizeof(GLuint))) 852#define RENDER_POINTS( start, count ) \ 853 for ( ; start < count ; start++) POINT( V(ELT(start)) ); 854#define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) ) 855#define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) ) 856#define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) ) 857#define INIT(x) intelRenderPrimitive( ctx, x ) 858#undef LOCAL_VARS 859#define LOCAL_VARS \ 860 struct intel_context *intel = intel_context(ctx); \ 861 GLubyte *vertptr = (GLubyte *)intel->verts; \ 862 const GLuint vertsize = intel->vertex_size; \ 863 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ 864 (void) elt; 865#define RESET_STIPPLE 866#define RESET_OCCLUSION 867#define PRESERVE_VB_DEFS 868#define ELT(x) x 869#define TAG(x) intel_##x##_verts 870#include "tnl/t_vb_rendertmp.h" 871#undef ELT 872#undef TAG 873#define TAG(x) intel_##x##_elts 874#define ELT(x) elt[x] 875#include "tnl/t_vb_rendertmp.h" 876 877/**********************************************************************/ 878/* Render clipped primitives */ 879/**********************************************************************/ 880 881 882 883static void 884intelRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n) 885{ 886 struct intel_context *intel = intel_context(ctx); 887 TNLcontext *tnl = TNL_CONTEXT(ctx); 888 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 889 GLuint prim = intel->render_primitive; 890 891 /* Render the new vertices as an unclipped polygon. 892 */ 893 { 894 GLuint *tmp = VB->Elts; 895 VB->Elts = (GLuint *) elts; 896 tnl->Driver.Render.PrimTabElts[GL_POLYGON] (ctx, 0, n, 897 PRIM_BEGIN | PRIM_END); 898 VB->Elts = tmp; 899 } 900 901 /* Restore the render primitive 902 */ 903 if (prim != GL_POLYGON) 904 tnl->Driver.Render.PrimitiveNotify(ctx, prim); 905} 906 907static void 908intelRenderClippedLine(GLcontext * ctx, GLuint ii, GLuint jj) 909{ 910 TNLcontext *tnl = TNL_CONTEXT(ctx); 911 912 tnl->Driver.Render.Line(ctx, ii, jj); 913} 914 915static void 916intelFastRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n) 917{ 918 struct intel_context *intel = intel_context(ctx); 919 const GLuint vertsize = intel->vertex_size; 920 GLuint *vb = intel_get_prim_space(intel, (n - 2) * 3); 921 GLubyte *vertptr = (GLubyte *) intel->verts; 922 const GLuint *start = (const GLuint *) V(elts[0]); 923 int i, j; 924 925 for (i = 2; i < n; i++) { 926 COPY_DWORDS(j, vb, vertsize, V(elts[i - 1])); 927 COPY_DWORDS(j, vb, vertsize, V(elts[i])); 928 COPY_DWORDS(j, vb, vertsize, start); 929 } 930} 931 932/**********************************************************************/ 933/* Choose render functions */ 934/**********************************************************************/ 935 936 937 938 939#define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN | DD_POINT_SMOOTH | DD_TRI_SMOOTH) 940#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED) 941 942void 943intelChooseRenderState(GLcontext * ctx) 944{ 945 TNLcontext *tnl = TNL_CONTEXT(ctx); 946 struct intel_context *intel = intel_context(ctx); 947 GLuint flags = ctx->_TriangleCaps; 948 const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; 949 GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS)); 950 GLuint index = 0; 951 952 if (INTEL_DEBUG & DEBUG_STATE) 953 fprintf(stderr, "\n%s\n", __FUNCTION__); 954 955 if ((flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) || have_wpos) { 956 957 if (flags & ANY_RASTER_FLAGS) { 958 if (flags & DD_TRI_LIGHT_TWOSIDE) 959 index |= INTEL_TWOSIDE_BIT; 960 if (flags & DD_TRI_OFFSET) 961 index |= INTEL_OFFSET_BIT; 962 if (flags & DD_TRI_UNFILLED) 963 index |= INTEL_UNFILLED_BIT; 964 } 965 966 if (have_wpos) { 967 intel->draw_point = intel_wpos_point; 968 intel->draw_line = intel_wpos_line; 969 intel->draw_tri = intel_wpos_triangle; 970 971 /* Make sure these get called: 972 */ 973 index |= INTEL_FALLBACK_BIT; 974 } 975 else { 976 intel->draw_point = intel_draw_point; 977 intel->draw_line = intel_draw_line; 978 intel->draw_tri = intel_draw_triangle; 979 } 980 981 /* Hook in fallbacks for specific primitives. 982 */ 983 if (flags & ANY_FALLBACK_FLAGS) { 984 if (flags & DD_LINE_STIPPLE) 985 intel->draw_line = intel_fallback_line; 986 987 if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple) 988 intel->draw_tri = intel_fallback_tri; 989 990 if (flags & DD_TRI_SMOOTH) { 991 if (intel->conformance_mode > 0) 992 intel->draw_tri = intel_fallback_tri; 993 } 994 995 if (flags & DD_POINT_ATTEN) { 996 if (0) 997 intel->draw_point = intel_atten_point; 998 else 999 intel->draw_point = intel_fallback_point; 1000 } 1001 1002 if (flags & DD_POINT_SMOOTH) { 1003 if (intel->conformance_mode > 0) 1004 intel->draw_point = intel_fallback_point; 1005 } 1006 1007 index |= INTEL_FALLBACK_BIT; 1008 } 1009 } 1010 1011 if (intel->RenderIndex != index) { 1012 intel->RenderIndex = index; 1013 1014 tnl->Driver.Render.Points = rast_tab[index].points; 1015 tnl->Driver.Render.Line = rast_tab[index].line; 1016 tnl->Driver.Render.Triangle = rast_tab[index].triangle; 1017 tnl->Driver.Render.Quad = rast_tab[index].quad; 1018 1019 if (index == 0) { 1020 tnl->Driver.Render.PrimTabVerts = intel_render_tab_verts; 1021 tnl->Driver.Render.PrimTabElts = intel_render_tab_elts; 1022 tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ 1023 tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly; 1024 } 1025 else { 1026 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; 1027 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; 1028 tnl->Driver.Render.ClippedLine = intelRenderClippedLine; 1029 tnl->Driver.Render.ClippedPolygon = intelRenderClippedPoly; 1030 } 1031 } 1032} 1033 1034static const GLenum reduced_prim[GL_POLYGON + 1] = { 1035 GL_POINTS, 1036 GL_LINES, 1037 GL_LINES, 1038 GL_LINES, 1039 GL_TRIANGLES, 1040 GL_TRIANGLES, 1041 GL_TRIANGLES, 1042 GL_TRIANGLES, 1043 GL_TRIANGLES, 1044 GL_TRIANGLES 1045}; 1046 1047 1048/**********************************************************************/ 1049/* High level hooks for t_vb_render.c */ 1050/**********************************************************************/ 1051 1052 1053 1054 1055static void 1056intelRunPipeline(GLcontext * ctx) 1057{ 1058 struct intel_context *intel = intel_context(ctx); 1059 1060 _mesa_lock_context_textures(ctx); 1061 1062 if (ctx->NewState) 1063 _mesa_update_state_locked(ctx); 1064 1065 if (intel->NewGLState) { 1066 if (intel->NewGLState & _NEW_TEXTURE) { 1067 intel->vtbl.update_texture_state(intel); 1068 } 1069 1070 if (!intel->Fallback) { 1071 if (intel->NewGLState & _INTEL_NEW_RENDERSTATE) 1072 intelChooseRenderState(ctx); 1073 } 1074 1075 intel->NewGLState = 0; 1076 } 1077 1078 intel_map_vertex_shader_textures(ctx); 1079 _tnl_run_pipeline(ctx); 1080 intel_unmap_vertex_shader_textures(ctx); 1081 1082 _mesa_unlock_context_textures(ctx); 1083} 1084 1085static void 1086intelRenderStart(GLcontext * ctx) 1087{ 1088 struct intel_context *intel = intel_context(ctx); 1089 1090 intel_check_front_buffer_rendering(intel); 1091 intel->vtbl.render_start(intel_context(ctx)); 1092 intel->vtbl.emit_state(intel); 1093} 1094 1095static void 1096intelRenderFinish(GLcontext * ctx) 1097{ 1098 struct intel_context *intel = intel_context(ctx); 1099 1100 if (intel->RenderIndex & INTEL_FALLBACK_BIT) 1101 _swrast_flush(ctx); 1102 1103 INTEL_FIREVERTICES(intel); 1104} 1105 1106 1107 1108 1109 /* System to flush dma and emit state changes based on the rasterized 1110 * primitive. 1111 */ 1112static void 1113intelRasterPrimitive(GLcontext * ctx, GLenum rprim, GLuint hwprim) 1114{ 1115 struct intel_context *intel = intel_context(ctx); 1116 1117 if (0) 1118 fprintf(stderr, "%s %s %x\n", __FUNCTION__, 1119 _mesa_lookup_enum_by_nr(rprim), hwprim); 1120 1121 intel->vtbl.reduced_primitive_state(intel, rprim); 1122 1123 /* Start a new primitive. Arrange to have it flushed later on. 1124 */ 1125 if (hwprim != intel->prim.primitive) { 1126 INTEL_FIREVERTICES(intel); 1127 1128 intel_set_prim(intel, hwprim); 1129 } 1130} 1131 1132 1133 /* 1134 */ 1135static void 1136intelRenderPrimitive(GLcontext * ctx, GLenum prim) 1137{ 1138 struct intel_context *intel = intel_context(ctx); 1139 1140 if (0) 1141 fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); 1142 1143 /* Let some clipping routines know which primitive they're dealing 1144 * with. 1145 */ 1146 intel->render_primitive = prim; 1147 1148 /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled 1149 * triangles. The rasterized primitive will always be reset by 1150 * lower level functions in that case, potentially pingponging the 1151 * state: 1152 */ 1153 if (reduced_prim[prim] == GL_TRIANGLES && 1154 (ctx->_TriangleCaps & DD_TRI_UNFILLED)) 1155 return; 1156 1157 /* Set some primitive-dependent state and Start? a new primitive. 1158 */ 1159 intelRasterPrimitive(ctx, reduced_prim[prim], hw_prim[prim]); 1160} 1161 1162 1163 /**********************************************************************/ 1164 /* Transition to/from hardware rasterization. */ 1165 /**********************************************************************/ 1166 1167static char *fallbackStrings[] = { 1168 [0] = "Draw buffer", 1169 [1] = "Read buffer", 1170 [2] = "Depth buffer", 1171 [3] = "Stencil buffer", 1172 [4] = "User disable", 1173 [5] = "Render mode", 1174 1175 [12] = "Texture", 1176 [13] = "Color mask", 1177 [14] = "Stencil", 1178 [15] = "Stipple", 1179 [16] = "Program", 1180 [17] = "Logic op", 1181 [18] = "Smooth polygon", 1182 [19] = "Smooth point", 1183}; 1184 1185 1186static char * 1187getFallbackString(GLuint bit) 1188{ 1189 int i = 0; 1190 while (bit > 1) { 1191 i++; 1192 bit >>= 1; 1193 } 1194 return fallbackStrings[i]; 1195} 1196 1197 1198 1199/** 1200 * Enable/disable a fallback flag. 1201 * \param bit one of INTEL_FALLBACK_x flags. 1202 */ 1203void 1204intelFallback(struct intel_context *intel, GLbitfield bit, GLboolean mode) 1205{ 1206 GLcontext *ctx = &intel->ctx; 1207 TNLcontext *tnl = TNL_CONTEXT(ctx); 1208 const GLbitfield oldfallback = intel->Fallback; 1209 1210 if (mode) { 1211 intel->Fallback |= bit; 1212 if (oldfallback == 0) { 1213 intelFlush(ctx); 1214 if (INTEL_DEBUG & DEBUG_FALLBACKS) 1215 fprintf(stderr, "ENTER FALLBACK %x: %s\n", 1216 bit, getFallbackString(bit)); 1217 _swsetup_Wakeup(ctx); 1218 intel->RenderIndex = ~0; 1219 } 1220 } 1221 else { 1222 intel->Fallback &= ~bit; 1223 if (oldfallback == bit) { 1224 _swrast_flush(ctx); 1225 if (INTEL_DEBUG & DEBUG_FALLBACKS) 1226 fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString(bit)); 1227 tnl->Driver.Render.Start = intelRenderStart; 1228 tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; 1229 tnl->Driver.Render.Finish = intelRenderFinish; 1230 tnl->Driver.Render.BuildVertices = _tnl_build_vertices; 1231 tnl->Driver.Render.CopyPV = _tnl_copy_pv; 1232 tnl->Driver.Render.Interp = _tnl_interp; 1233 1234 _tnl_invalidate_vertex_state(ctx, ~0); 1235 _tnl_invalidate_vertices(ctx, ~0); 1236 _tnl_install_attrs(ctx, 1237 intel->vertex_attrs, 1238 intel->vertex_attr_count, 1239 intel->ViewportMatrix.m, 0); 1240 1241 intel->NewGLState |= _INTEL_NEW_RENDERSTATE; 1242 } 1243 } 1244} 1245 1246union fi 1247{ 1248 GLfloat f; 1249 GLint i; 1250}; 1251 1252/**********************************************************************/ 1253/* Initialization. */ 1254/**********************************************************************/ 1255 1256 1257void 1258intelInitTriFuncs(GLcontext * ctx) 1259{ 1260 TNLcontext *tnl = TNL_CONTEXT(ctx); 1261 static int firsttime = 1; 1262 1263 if (firsttime) { 1264 init_rast_tab(); 1265 firsttime = 0; 1266 } 1267 1268 tnl->Driver.RunPipeline = intelRunPipeline; 1269 tnl->Driver.Render.Start = intelRenderStart; 1270 tnl->Driver.Render.Finish = intelRenderFinish; 1271 tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; 1272 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; 1273 tnl->Driver.Render.BuildVertices = _tnl_build_vertices; 1274 tnl->Driver.Render.CopyPV = _tnl_copy_pv; 1275 tnl->Driver.Render.Interp = _tnl_interp; 1276} 1277