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