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