draw_pipe_aaline.c revision 5b0824dfe5eaf59fa87134e7482b3d147b262901
1/************************************************************************** 2 * 3 * Copyright 2007 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/** 29 * AA line stage: AA lines are converted to texture mapped triangles. 30 * 31 * Authors: Brian Paul 32 */ 33 34 35#include "pipe/p_context.h" 36#include "pipe/p_defines.h" 37#include "pipe/p_shader_tokens.h" 38#include "util/u_math.h" 39#include "util/u_memory.h" 40 41#include "tgsi/tgsi_transform.h" 42#include "tgsi/tgsi_dump.h" 43 44#include "draw_context.h" 45#include "draw_private.h" 46#include "draw_pipe.h" 47 48 49/** 50 * Max texture level for the alpha texture used for antialiasing 51 */ 52#define MAX_TEXTURE_LEVEL 5 /* 32 x 32 */ 53 54 55/** 56 * Subclass of pipe_shader_state to carry extra fragment shader info. 57 */ 58struct aaline_fragment_shader 59{ 60 struct pipe_shader_state state; 61 void *driver_fs; 62 void *aaline_fs; 63 uint sampler_unit; 64 int generic_attrib; /**< texcoord/generic used for texture */ 65}; 66 67 68/** 69 * Subclass of draw_stage 70 */ 71struct aaline_stage 72{ 73 struct draw_stage stage; 74 75 float half_line_width; 76 77 /** For AA lines, this is the vertex attrib slot for the new texcoords */ 78 uint tex_slot; 79 /** position, not necessarily output zero */ 80 uint pos_slot; 81 82 void *sampler_cso; 83 struct pipe_texture *texture; 84 uint num_samplers; 85 uint num_textures; 86 87 88 /* 89 * Currently bound state 90 */ 91 struct aaline_fragment_shader *fs; 92 struct { 93 void *sampler[PIPE_MAX_SAMPLERS]; 94 struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; 95 } state; 96 97 /* 98 * Driver interface/override functions 99 */ 100 void * (*driver_create_fs_state)(struct pipe_context *, 101 const struct pipe_shader_state *); 102 void (*driver_bind_fs_state)(struct pipe_context *, void *); 103 void (*driver_delete_fs_state)(struct pipe_context *, void *); 104 105 void (*driver_bind_sampler_states)(struct pipe_context *, unsigned, 106 void **); 107 void (*driver_set_sampler_textures)(struct pipe_context *, unsigned, 108 struct pipe_texture **); 109 110 struct pipe_context *pipe; 111}; 112 113 114 115/** 116 * Subclass of tgsi_transform_context, used for transforming the 117 * user's fragment shader to add the special AA instructions. 118 */ 119struct aa_transform_context { 120 struct tgsi_transform_context base; 121 uint tempsUsed; /**< bitmask */ 122 int colorOutput; /**< which output is the primary color */ 123 uint samplersUsed; /**< bitfield of samplers used */ 124 int freeSampler; /** an available sampler for the pstipple */ 125 int maxInput, maxGeneric; /**< max input index found */ 126 int colorTemp, texTemp; /**< temp registers */ 127 boolean firstInstruction; 128}; 129 130 131/** 132 * TGSI declaration transform callback. 133 * Look for a free sampler, a free input attrib, and two free temp regs. 134 */ 135static void 136aa_transform_decl(struct tgsi_transform_context *ctx, 137 struct tgsi_full_declaration *decl) 138{ 139 struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; 140 141 if (decl->Declaration.File == TGSI_FILE_OUTPUT && 142 decl->Semantic.Name == TGSI_SEMANTIC_COLOR && 143 decl->Semantic.Index == 0) { 144 aactx->colorOutput = decl->Range.First; 145 } 146 else if (decl->Declaration.File == TGSI_FILE_SAMPLER) { 147 uint i; 148 for (i = decl->Range.First; 149 i <= decl->Range.Last; i++) { 150 aactx->samplersUsed |= 1 << i; 151 } 152 } 153 else if (decl->Declaration.File == TGSI_FILE_INPUT) { 154 if ((int) decl->Range.Last > aactx->maxInput) 155 aactx->maxInput = decl->Range.Last; 156 if (decl->Semantic.Name == TGSI_SEMANTIC_GENERIC && 157 (int) decl->Semantic.Index > aactx->maxGeneric) { 158 aactx->maxGeneric = decl->Semantic.Index; 159 } 160 } 161 else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { 162 uint i; 163 for (i = decl->Range.First; 164 i <= decl->Range.Last; i++) { 165 aactx->tempsUsed |= (1 << i); 166 } 167 } 168 169 ctx->emit_declaration(ctx, decl); 170} 171 172 173/** 174 * Find the lowest zero bit in the given word, or -1 if bitfield is all ones. 175 */ 176static int 177free_bit(uint bitfield) 178{ 179 int i; 180 for (i = 0; i < 32; i++) { 181 if ((bitfield & (1 << i)) == 0) 182 return i; 183 } 184 return -1; 185} 186 187 188/** 189 * TGSI instruction transform callback. 190 * Replace writes to result.color w/ a temp reg. 191 * Upon END instruction, insert texture sampling code for antialiasing. 192 */ 193static void 194aa_transform_inst(struct tgsi_transform_context *ctx, 195 struct tgsi_full_instruction *inst) 196{ 197 struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; 198 199 if (aactx->firstInstruction) { 200 /* emit our new declarations before the first instruction */ 201 202 struct tgsi_full_declaration decl; 203 uint i; 204 205 /* find free sampler */ 206 aactx->freeSampler = free_bit(aactx->samplersUsed); 207 if (aactx->freeSampler >= PIPE_MAX_SAMPLERS) 208 aactx->freeSampler = PIPE_MAX_SAMPLERS - 1; 209 210 /* find two free temp regs */ 211 for (i = 0; i < 32; i++) { 212 if ((aactx->tempsUsed & (1 << i)) == 0) { 213 /* found a free temp */ 214 if (aactx->colorTemp < 0) 215 aactx->colorTemp = i; 216 else if (aactx->texTemp < 0) 217 aactx->texTemp = i; 218 else 219 break; 220 } 221 } 222 assert(aactx->colorTemp >= 0); 223 assert(aactx->texTemp >= 0); 224 225 /* declare new generic input/texcoord */ 226 decl = tgsi_default_full_declaration(); 227 decl.Declaration.File = TGSI_FILE_INPUT; 228 /* XXX this could be linear... */ 229 decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; 230 decl.Declaration.Semantic = 1; 231 decl.Semantic.Name = TGSI_SEMANTIC_GENERIC; 232 decl.Semantic.Index = aactx->maxGeneric + 1; 233 decl.Range.First = 234 decl.Range.Last = aactx->maxInput + 1; 235 ctx->emit_declaration(ctx, &decl); 236 237 /* declare new sampler */ 238 decl = tgsi_default_full_declaration(); 239 decl.Declaration.File = TGSI_FILE_SAMPLER; 240 decl.Range.First = 241 decl.Range.Last = aactx->freeSampler; 242 ctx->emit_declaration(ctx, &decl); 243 244 /* declare new temp regs */ 245 decl = tgsi_default_full_declaration(); 246 decl.Declaration.File = TGSI_FILE_TEMPORARY; 247 decl.Range.First = 248 decl.Range.Last = aactx->texTemp; 249 ctx->emit_declaration(ctx, &decl); 250 251 decl = tgsi_default_full_declaration(); 252 decl.Declaration.File = TGSI_FILE_TEMPORARY; 253 decl.Range.First = 254 decl.Range.Last = aactx->colorTemp; 255 ctx->emit_declaration(ctx, &decl); 256 257 aactx->firstInstruction = FALSE; 258 } 259 260 if (inst->Instruction.Opcode == TGSI_OPCODE_END && 261 aactx->colorOutput != -1) { 262 struct tgsi_full_instruction newInst; 263 264 /* TEX */ 265 newInst = tgsi_default_full_instruction(); 266 newInst.Instruction.Opcode = TGSI_OPCODE_TEX; 267 newInst.Instruction.NumDstRegs = 1; 268 newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; 269 newInst.Dst[0].Register.Index = aactx->texTemp; 270 newInst.Instruction.NumSrcRegs = 2; 271 newInst.Instruction.Texture = TRUE; 272 newInst.Texture.Texture = TGSI_TEXTURE_2D; 273 newInst.Src[0].SrcRegister.File = TGSI_FILE_INPUT; 274 newInst.Src[0].SrcRegister.Index = aactx->maxInput + 1; 275 newInst.Src[1].SrcRegister.File = TGSI_FILE_SAMPLER; 276 newInst.Src[1].SrcRegister.Index = aactx->freeSampler; 277 278 ctx->emit_instruction(ctx, &newInst); 279 280 /* MOV rgb */ 281 newInst = tgsi_default_full_instruction(); 282 newInst.Instruction.Opcode = TGSI_OPCODE_MOV; 283 newInst.Instruction.NumDstRegs = 1; 284 newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT; 285 newInst.Dst[0].Register.Index = aactx->colorOutput; 286 newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZ; 287 newInst.Instruction.NumSrcRegs = 1; 288 newInst.Src[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 289 newInst.Src[0].SrcRegister.Index = aactx->colorTemp; 290 ctx->emit_instruction(ctx, &newInst); 291 292 /* MUL alpha */ 293 newInst = tgsi_default_full_instruction(); 294 newInst.Instruction.Opcode = TGSI_OPCODE_MUL; 295 newInst.Instruction.NumDstRegs = 1; 296 newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT; 297 newInst.Dst[0].Register.Index = aactx->colorOutput; 298 newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_W; 299 newInst.Instruction.NumSrcRegs = 2; 300 newInst.Src[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 301 newInst.Src[0].SrcRegister.Index = aactx->colorTemp; 302 newInst.Src[1].SrcRegister.File = TGSI_FILE_TEMPORARY; 303 newInst.Src[1].SrcRegister.Index = aactx->texTemp; 304 ctx->emit_instruction(ctx, &newInst); 305 306 /* END */ 307 newInst = tgsi_default_full_instruction(); 308 newInst.Instruction.Opcode = TGSI_OPCODE_END; 309 newInst.Instruction.NumDstRegs = 0; 310 newInst.Instruction.NumSrcRegs = 0; 311 ctx->emit_instruction(ctx, &newInst); 312 } 313 else { 314 /* Not an END instruction. 315 * Look for writes to result.color and replace with colorTemp reg. 316 */ 317 uint i; 318 319 for (i = 0; i < inst->Instruction.NumDstRegs; i++) { 320 struct tgsi_full_dst_register *dst = &inst->Dst[i]; 321 if (dst->Register.File == TGSI_FILE_OUTPUT && 322 dst->Register.Index == aactx->colorOutput) { 323 dst->Register.File = TGSI_FILE_TEMPORARY; 324 dst->Register.Index = aactx->colorTemp; 325 } 326 } 327 328 ctx->emit_instruction(ctx, inst); 329 } 330} 331 332 333/** 334 * Generate the frag shader we'll use for drawing AA lines. 335 * This will be the user's shader plus some texture/modulate instructions. 336 */ 337static boolean 338generate_aaline_fs(struct aaline_stage *aaline) 339{ 340 const struct pipe_shader_state *orig_fs = &aaline->fs->state; 341 struct pipe_shader_state aaline_fs; 342 struct aa_transform_context transform; 343 344#define MAX 1000 345 346 aaline_fs = *orig_fs; /* copy to init */ 347 aaline_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX); 348 if (aaline_fs.tokens == NULL) 349 return FALSE; 350 351 memset(&transform, 0, sizeof(transform)); 352 transform.colorOutput = -1; 353 transform.maxInput = -1; 354 transform.maxGeneric = -1; 355 transform.colorTemp = -1; 356 transform.texTemp = -1; 357 transform.firstInstruction = TRUE; 358 transform.base.transform_instruction = aa_transform_inst; 359 transform.base.transform_declaration = aa_transform_decl; 360 361 tgsi_transform_shader(orig_fs->tokens, 362 (struct tgsi_token *) aaline_fs.tokens, 363 MAX, &transform.base); 364 365#if 0 /* DEBUG */ 366 tgsi_dump(orig_fs->tokens, 0); 367 tgsi_dump(aaline_fs.tokens, 0); 368#endif 369 370 aaline->fs->sampler_unit = transform.freeSampler; 371 372 aaline->fs->aaline_fs 373 = aaline->driver_create_fs_state(aaline->pipe, &aaline_fs); 374 if (aaline->fs->aaline_fs == NULL) 375 goto fail; 376 377 aaline->fs->generic_attrib = transform.maxGeneric + 1; 378 FREE((void *)aaline_fs.tokens); 379 return TRUE; 380 381fail: 382 FREE((void *)aaline_fs.tokens); 383 return FALSE; 384} 385 386 387/** 388 * Create the texture map we'll use for antialiasing the lines. 389 */ 390static boolean 391aaline_create_texture(struct aaline_stage *aaline) 392{ 393 struct pipe_context *pipe = aaline->pipe; 394 struct pipe_screen *screen = pipe->screen; 395 struct pipe_texture texTemp; 396 uint level; 397 398 memset(&texTemp, 0, sizeof(texTemp)); 399 texTemp.target = PIPE_TEXTURE_2D; 400 texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */ 401 texTemp.last_level = MAX_TEXTURE_LEVEL; 402 texTemp.width[0] = 1 << MAX_TEXTURE_LEVEL; 403 texTemp.height[0] = 1 << MAX_TEXTURE_LEVEL; 404 texTemp.depth[0] = 1; 405 pf_get_block(texTemp.format, &texTemp.block); 406 407 aaline->texture = screen->texture_create(screen, &texTemp); 408 if (!aaline->texture) 409 return FALSE; 410 411 /* Fill in mipmap images. 412 * Basically each level is solid opaque, except for the outermost 413 * texels which are zero. Special case the 1x1 and 2x2 levels. 414 */ 415 for (level = 0; level <= MAX_TEXTURE_LEVEL; level++) { 416 struct pipe_transfer *transfer; 417 const uint size = aaline->texture->width[level]; 418 ubyte *data; 419 uint i, j; 420 421 assert(aaline->texture->width[level] == aaline->texture->height[level]); 422 423 /* This texture is new, no need to flush. 424 */ 425 transfer = screen->get_tex_transfer(screen, aaline->texture, 0, level, 0, 426 PIPE_TRANSFER_WRITE, 0, 0, size, size); 427 data = screen->transfer_map(screen, transfer); 428 if (data == NULL) 429 return FALSE; 430 431 for (i = 0; i < size; i++) { 432 for (j = 0; j < size; j++) { 433 ubyte d; 434 if (size == 1) { 435 d = 255; 436 } 437 else if (size == 2) { 438 d = 200; /* tuneable */ 439 } 440 else if (i == 0 || j == 0 || i == size - 1 || j == size - 1) { 441 d = 0; 442 } 443 else { 444 d = 255; 445 } 446 data[i * transfer->stride + j] = d; 447 } 448 } 449 450 /* unmap */ 451 screen->transfer_unmap(screen, transfer); 452 screen->tex_transfer_destroy(transfer); 453 } 454 return TRUE; 455} 456 457 458/** 459 * Create the sampler CSO that'll be used for antialiasing. 460 * By using a mipmapped texture, we don't have to generate a different 461 * texture image for each line size. 462 */ 463static boolean 464aaline_create_sampler(struct aaline_stage *aaline) 465{ 466 struct pipe_sampler_state sampler; 467 struct pipe_context *pipe = aaline->pipe; 468 469 memset(&sampler, 0, sizeof(sampler)); 470 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 471 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 472 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 473 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR; 474 sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; 475 sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; 476 sampler.normalized_coords = 1; 477 sampler.min_lod = 0.0f; 478 sampler.max_lod = MAX_TEXTURE_LEVEL; 479 480 aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler); 481 if (aaline->sampler_cso == NULL) 482 return FALSE; 483 484 return TRUE; 485} 486 487 488/** 489 * When we're about to draw our first AA line in a batch, this function is 490 * called to tell the driver to bind our modified fragment shader. 491 */ 492static boolean 493bind_aaline_fragment_shader(struct aaline_stage *aaline) 494{ 495 struct draw_context *draw = aaline->stage.draw; 496 497 if (!aaline->fs->aaline_fs && 498 !generate_aaline_fs(aaline)) 499 return FALSE; 500 501 draw->suspend_flushing = TRUE; 502 aaline->driver_bind_fs_state(aaline->pipe, aaline->fs->aaline_fs); 503 draw->suspend_flushing = FALSE; 504 505 return TRUE; 506} 507 508 509 510static INLINE struct aaline_stage * 511aaline_stage( struct draw_stage *stage ) 512{ 513 return (struct aaline_stage *) stage; 514} 515 516 517/** 518 * Draw a wide line by drawing a quad, using geometry which will 519 * fullfill GL's antialiased line requirements. 520 */ 521static void 522aaline_line(struct draw_stage *stage, struct prim_header *header) 523{ 524 const struct aaline_stage *aaline = aaline_stage(stage); 525 const float half_width = aaline->half_line_width; 526 struct prim_header tri; 527 struct vertex_header *v[8]; 528 uint texPos = aaline->tex_slot; 529 uint posPos = aaline->pos_slot; 530 float *pos, *tex; 531 float dx = header->v[1]->data[posPos][0] - header->v[0]->data[posPos][0]; 532 float dy = header->v[1]->data[posPos][1] - header->v[0]->data[posPos][1]; 533 double a = atan2(dy, dx); 534 float c_a = (float) cos(a), s_a = (float) sin(a); 535 uint i; 536 537 /* XXX the ends of lines aren't quite perfect yet, but probably passable */ 538 dx = 0.5F * half_width; 539 dy = half_width; 540 541 /* allocate/dup new verts */ 542 for (i = 0; i < 8; i++) { 543 v[i] = dup_vert(stage, header->v[i/4], i); 544 } 545 546 /* 547 * Quad strip for line from v0 to v1 (*=endpoints): 548 * 549 * 1 3 5 7 550 * +---+---------------------+---+ 551 * | | 552 * | *v0 v1* | 553 * | | 554 * +---+---------------------+---+ 555 * 0 2 4 6 556 */ 557 558 /* new verts */ 559 pos = v[0]->data[posPos]; 560 pos[0] += (-dx * c_a - dy * s_a); 561 pos[1] += (-dx * s_a + dy * c_a); 562 563 pos = v[1]->data[posPos]; 564 pos[0] += (-dx * c_a - -dy * s_a); 565 pos[1] += (-dx * s_a + -dy * c_a); 566 567 pos = v[2]->data[posPos]; 568 pos[0] += ( dx * c_a - dy * s_a); 569 pos[1] += ( dx * s_a + dy * c_a); 570 571 pos = v[3]->data[posPos]; 572 pos[0] += ( dx * c_a - -dy * s_a); 573 pos[1] += ( dx * s_a + -dy * c_a); 574 575 pos = v[4]->data[posPos]; 576 pos[0] += (-dx * c_a - dy * s_a); 577 pos[1] += (-dx * s_a + dy * c_a); 578 579 pos = v[5]->data[posPos]; 580 pos[0] += (-dx * c_a - -dy * s_a); 581 pos[1] += (-dx * s_a + -dy * c_a); 582 583 pos = v[6]->data[posPos]; 584 pos[0] += ( dx * c_a - dy * s_a); 585 pos[1] += ( dx * s_a + dy * c_a); 586 587 pos = v[7]->data[posPos]; 588 pos[0] += ( dx * c_a - -dy * s_a); 589 pos[1] += ( dx * s_a + -dy * c_a); 590 591 /* new texcoords */ 592 tex = v[0]->data[texPos]; 593 ASSIGN_4V(tex, 0, 0, 0, 1); 594 595 tex = v[1]->data[texPos]; 596 ASSIGN_4V(tex, 0, 1, 0, 1); 597 598 tex = v[2]->data[texPos]; 599 ASSIGN_4V(tex, .5, 0, 0, 1); 600 601 tex = v[3]->data[texPos]; 602 ASSIGN_4V(tex, .5, 1, 0, 1); 603 604 tex = v[4]->data[texPos]; 605 ASSIGN_4V(tex, .5, 0, 0, 1); 606 607 tex = v[5]->data[texPos]; 608 ASSIGN_4V(tex, .5, 1, 0, 1); 609 610 tex = v[6]->data[texPos]; 611 ASSIGN_4V(tex, 1, 0, 0, 1); 612 613 tex = v[7]->data[texPos]; 614 ASSIGN_4V(tex, 1, 1, 0, 1); 615 616 /* emit 6 tris for the quad strip */ 617 tri.v[0] = v[2]; tri.v[1] = v[1]; tri.v[2] = v[0]; 618 stage->next->tri( stage->next, &tri ); 619 620 tri.v[0] = v[3]; tri.v[1] = v[1]; tri.v[2] = v[2]; 621 stage->next->tri( stage->next, &tri ); 622 623 tri.v[0] = v[4]; tri.v[1] = v[3]; tri.v[2] = v[2]; 624 stage->next->tri( stage->next, &tri ); 625 626 tri.v[0] = v[5]; tri.v[1] = v[3]; tri.v[2] = v[4]; 627 stage->next->tri( stage->next, &tri ); 628 629 tri.v[0] = v[6]; tri.v[1] = v[5]; tri.v[2] = v[4]; 630 stage->next->tri( stage->next, &tri ); 631 632 tri.v[0] = v[7]; tri.v[1] = v[5]; tri.v[2] = v[6]; 633 stage->next->tri( stage->next, &tri ); 634} 635 636 637static void 638aaline_first_line(struct draw_stage *stage, struct prim_header *header) 639{ 640 auto struct aaline_stage *aaline = aaline_stage(stage); 641 struct draw_context *draw = stage->draw; 642 struct pipe_context *pipe = aaline->pipe; 643 uint num_samplers; 644 645 assert(draw->rasterizer->line_smooth); 646 647 if (draw->rasterizer->line_width <= 3.0) 648 aaline->half_line_width = 1.5f; 649 else 650 aaline->half_line_width = 0.5f * draw->rasterizer->line_width; 651 652 /* 653 * Bind (generate) our fragprog, sampler and texture 654 */ 655 if (!bind_aaline_fragment_shader(aaline)) { 656 stage->line = draw_pipe_passthrough_line; 657 stage->line(stage, header); 658 return; 659 } 660 661 /* update vertex attrib info */ 662 aaline->tex_slot = draw->vs.num_vs_outputs; 663 aaline->pos_slot = draw->vs.position_output; 664 665 /* advertise the extra post-transformed vertex attribute */ 666 draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; 667 draw->extra_vp_outputs.semantic_index = aaline->fs->generic_attrib; 668 draw->extra_vp_outputs.slot = aaline->tex_slot; 669 670 /* how many samplers? */ 671 /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */ 672 num_samplers = MAX2(aaline->num_textures, aaline->num_samplers); 673 num_samplers = MAX2(num_samplers, aaline->fs->sampler_unit + 1); 674 675 aaline->state.sampler[aaline->fs->sampler_unit] = aaline->sampler_cso; 676 pipe_texture_reference(&aaline->state.texture[aaline->fs->sampler_unit], 677 aaline->texture); 678 679 draw->suspend_flushing = TRUE; 680 aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler); 681 aaline->driver_set_sampler_textures(pipe, num_samplers, aaline->state.texture); 682 draw->suspend_flushing = FALSE; 683 684 /* now really draw first line */ 685 stage->line = aaline_line; 686 stage->line(stage, header); 687} 688 689 690static void 691aaline_flush(struct draw_stage *stage, unsigned flags) 692{ 693 struct draw_context *draw = stage->draw; 694 struct aaline_stage *aaline = aaline_stage(stage); 695 struct pipe_context *pipe = aaline->pipe; 696 697 stage->line = aaline_first_line; 698 stage->next->flush( stage->next, flags ); 699 700 /* restore original frag shader, texture, sampler state */ 701 draw->suspend_flushing = TRUE; 702 aaline->driver_bind_fs_state(pipe, aaline->fs->driver_fs); 703 aaline->driver_bind_sampler_states(pipe, aaline->num_samplers, 704 aaline->state.sampler); 705 aaline->driver_set_sampler_textures(pipe, aaline->num_textures, 706 aaline->state.texture); 707 draw->suspend_flushing = FALSE; 708 709 draw->extra_vp_outputs.slot = 0; 710} 711 712 713static void 714aaline_reset_stipple_counter(struct draw_stage *stage) 715{ 716 stage->next->reset_stipple_counter( stage->next ); 717} 718 719 720static void 721aaline_destroy(struct draw_stage *stage) 722{ 723 struct aaline_stage *aaline = aaline_stage(stage); 724 uint i; 725 726 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 727 pipe_texture_reference(&aaline->state.texture[i], NULL); 728 } 729 730 if (aaline->sampler_cso) 731 aaline->pipe->delete_sampler_state(aaline->pipe, aaline->sampler_cso); 732 733 if (aaline->texture) 734 pipe_texture_reference(&aaline->texture, NULL); 735 736 draw_free_temp_verts( stage ); 737 738 FREE( stage ); 739} 740 741 742static struct aaline_stage * 743draw_aaline_stage(struct draw_context *draw) 744{ 745 struct aaline_stage *aaline = CALLOC_STRUCT(aaline_stage); 746 if (aaline == NULL) 747 return NULL; 748 749 if (!draw_alloc_temp_verts( &aaline->stage, 8 )) 750 goto fail; 751 752 aaline->stage.draw = draw; 753 aaline->stage.name = "aaline"; 754 aaline->stage.next = NULL; 755 aaline->stage.point = draw_pipe_passthrough_point; 756 aaline->stage.line = aaline_first_line; 757 aaline->stage.tri = draw_pipe_passthrough_tri; 758 aaline->stage.flush = aaline_flush; 759 aaline->stage.reset_stipple_counter = aaline_reset_stipple_counter; 760 aaline->stage.destroy = aaline_destroy; 761 762 return aaline; 763 764 fail: 765 if (aaline) 766 aaline_destroy(&aaline->stage); 767 768 return NULL; 769} 770 771 772static struct aaline_stage * 773aaline_stage_from_pipe(struct pipe_context *pipe) 774{ 775 struct draw_context *draw = (struct draw_context *) pipe->draw; 776 return aaline_stage(draw->pipeline.aaline); 777} 778 779 780/** 781 * This function overrides the driver's create_fs_state() function and 782 * will typically be called by the state tracker. 783 */ 784static void * 785aaline_create_fs_state(struct pipe_context *pipe, 786 const struct pipe_shader_state *fs) 787{ 788 struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); 789 struct aaline_fragment_shader *aafs = CALLOC_STRUCT(aaline_fragment_shader); 790 if (aafs == NULL) 791 return NULL; 792 793 aafs->state = *fs; 794 795 /* pass-through */ 796 aafs->driver_fs = aaline->driver_create_fs_state(aaline->pipe, fs); 797 798 return aafs; 799} 800 801 802static void 803aaline_bind_fs_state(struct pipe_context *pipe, void *fs) 804{ 805 struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); 806 struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs; 807 808 /* save current */ 809 aaline->fs = aafs; 810 /* pass-through */ 811 aaline->driver_bind_fs_state(aaline->pipe, 812 (aafs ? aafs->driver_fs : NULL)); 813} 814 815 816static void 817aaline_delete_fs_state(struct pipe_context *pipe, void *fs) 818{ 819 struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); 820 struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs; 821 /* pass-through */ 822 aaline->driver_delete_fs_state(aaline->pipe, aafs->driver_fs); 823 824 if (aafs->aaline_fs) 825 aaline->driver_delete_fs_state(aaline->pipe, aafs->aaline_fs); 826 827 FREE(aafs); 828} 829 830 831static void 832aaline_bind_sampler_states(struct pipe_context *pipe, 833 unsigned num, void **sampler) 834{ 835 struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); 836 837 /* save current */ 838 memcpy(aaline->state.sampler, sampler, num * sizeof(void *)); 839 aaline->num_samplers = num; 840 841 /* pass-through */ 842 aaline->driver_bind_sampler_states(aaline->pipe, num, sampler); 843} 844 845 846static void 847aaline_set_sampler_textures(struct pipe_context *pipe, 848 unsigned num, struct pipe_texture **texture) 849{ 850 struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); 851 uint i; 852 853 /* save current */ 854 for (i = 0; i < num; i++) { 855 pipe_texture_reference(&aaline->state.texture[i], texture[i]); 856 } 857 for ( ; i < PIPE_MAX_SAMPLERS; i++) { 858 pipe_texture_reference(&aaline->state.texture[i], NULL); 859 } 860 aaline->num_textures = num; 861 862 /* pass-through */ 863 aaline->driver_set_sampler_textures(aaline->pipe, num, texture); 864} 865 866 867/** 868 * Called by drivers that want to install this AA line prim stage 869 * into the draw module's pipeline. This will not be used if the 870 * hardware has native support for AA lines. 871 */ 872boolean 873draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe) 874{ 875 struct aaline_stage *aaline; 876 877 pipe->draw = (void *) draw; 878 879 /* 880 * Create / install AA line drawing / prim stage 881 */ 882 aaline = draw_aaline_stage( draw ); 883 if (!aaline) 884 goto fail; 885 886 aaline->pipe = pipe; 887 888 /* create special texture, sampler state */ 889 if (!aaline_create_texture(aaline)) 890 goto fail; 891 892 if (!aaline_create_sampler(aaline)) 893 goto fail; 894 895 /* save original driver functions */ 896 aaline->driver_create_fs_state = pipe->create_fs_state; 897 aaline->driver_bind_fs_state = pipe->bind_fs_state; 898 aaline->driver_delete_fs_state = pipe->delete_fs_state; 899 900 aaline->driver_bind_sampler_states = pipe->bind_sampler_states; 901 aaline->driver_set_sampler_textures = pipe->set_sampler_textures; 902 903 /* override the driver's functions */ 904 pipe->create_fs_state = aaline_create_fs_state; 905 pipe->bind_fs_state = aaline_bind_fs_state; 906 pipe->delete_fs_state = aaline_delete_fs_state; 907 908 pipe->bind_sampler_states = aaline_bind_sampler_states; 909 pipe->set_sampler_textures = aaline_set_sampler_textures; 910 911 /* Install once everything is known to be OK: 912 */ 913 draw->pipeline.aaline = &aaline->stage; 914 915 return TRUE; 916 917 fail: 918 if (aaline) 919 aaline->stage.destroy( &aaline->stage ); 920 921 return FALSE; 922} 923