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