Go to the source code of this file.
Data Structures | |
struct | aapoint_fragment_shader |
Subclass of pipe_shader_state to carry extra fragment shader info. More... | |
struct | aapoint_stage |
Subclass of draw_stage. More... | |
struct | aa_transform_context |
Subclass of tgsi_transform_context, used for transforming the user's fragment shader to add the special AA instructions. More... | |
Defines | |
#define | NORMALIZE 0 |
AA point stage: AA points are converted to quads and rendered with a special fragment shader. | |
#define | MAX 1000 |
Functions | |
static void | aa_transform_decl (struct tgsi_transform_context *ctx, struct tgsi_full_declaration *decl) |
TGSI declaration transform callback. | |
static void | aa_transform_inst (struct tgsi_transform_context *ctx, struct tgsi_full_instruction *inst) |
TGSI instruction transform callback. | |
static boolean | generate_aapoint_fs (struct aapoint_stage *aapoint) |
Generate the frag shader we'll use for drawing AA points. | |
static boolean | bind_aapoint_fragment_shader (struct aapoint_stage *aapoint) |
When we're about to draw our first AA point in a batch, this function is called to tell the driver to bind our modified fragment shader. | |
static struct aapoint_stage * | aapoint_stage (struct draw_stage *stage) |
static void | aapoint_point (struct draw_stage *stage, struct prim_header *header) |
Draw an AA point by drawing a quad. | |
static void | aapoint_first_point (struct draw_stage *stage, struct prim_header *header) |
static void | aapoint_flush (struct draw_stage *stage, unsigned flags) |
static void | aapoint_reset_stipple_counter (struct draw_stage *stage) |
static void | aapoint_destroy (struct draw_stage *stage) |
static struct aapoint_stage * | draw_aapoint_stage (struct draw_context *draw) |
static struct aapoint_stage * | aapoint_stage_from_pipe (struct pipe_context *pipe) |
static void * | aapoint_create_fs_state (struct pipe_context *pipe, const struct pipe_shader_state *fs) |
This function overrides the driver's create_fs_state() function and will typically be called by the state tracker. | |
static void | aapoint_bind_fs_state (struct pipe_context *pipe, void *fs) |
static void | aapoint_delete_fs_state (struct pipe_context *pipe, void *fs) |
boolean | draw_install_aapoint_stage (struct draw_context *draw, struct pipe_context *pipe) |
Called by drivers that want to install this AA point prim stage into the draw module's pipeline. |
#define MAX 1000 |
#define NORMALIZE 0 |
AA point stage: AA points are converted to quads and rendered with a special fragment shader.
Another approach would be to use a texture map image of a point, but experiments indicate the quality isn't nearly as good as this approach.
Note: this looks a lot like draw_aaline.c but there's actually little if any code that can be shared.
Authors: Brian Paul
Definition at line 63 of file draw_pipe_aapoint.c.
static void aa_transform_decl | ( | struct tgsi_transform_context * | ctx, | |
struct tgsi_full_declaration * | decl | |||
) | [static] |
TGSI declaration transform callback.
Look for two free temp regs and available input reg for new texcoords.
Definition at line 129 of file draw_pipe_aapoint.c.
References aa_transform_context::colorOutput, tgsi_full_declaration::Declaration, tgsi_full_declaration::DeclarationRange, tgsi_transform_context::emit_declaration, tgsi_declaration::File, tgsi_declaration_range::First, tgsi_declaration_range::Last, aa_transform_context::maxGeneric, aa_transform_context::maxInput, tgsi_full_declaration::Semantic, tgsi_declaration_semantic::SemanticIndex, tgsi_declaration_semantic::SemanticName, aa_transform_context::tempsUsed, TGSI_FILE_INPUT, TGSI_FILE_OUTPUT, TGSI_FILE_TEMPORARY, TGSI_SEMANTIC_COLOR, and TGSI_SEMANTIC_GENERIC.
00131 { 00132 struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; 00133 00134 if (decl->Declaration.File == TGSI_FILE_OUTPUT && 00135 decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR && 00136 decl->Semantic.SemanticIndex == 0) { 00137 aactx->colorOutput = decl->DeclarationRange.First; 00138 } 00139 else if (decl->Declaration.File == TGSI_FILE_INPUT) { 00140 if ((int) decl->DeclarationRange.Last > aactx->maxInput) 00141 aactx->maxInput = decl->DeclarationRange.Last; 00142 if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC && 00143 (int) decl->Semantic.SemanticIndex > aactx->maxGeneric) { 00144 aactx->maxGeneric = decl->Semantic.SemanticIndex; 00145 } 00146 } 00147 else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { 00148 uint i; 00149 for (i = decl->DeclarationRange.First; 00150 i <= decl->DeclarationRange.Last; i++) { 00151 aactx->tempsUsed |= (1 << i); 00152 } 00153 } 00154 00155 ctx->emit_declaration(ctx, decl); 00156 }
static void aa_transform_inst | ( | struct tgsi_transform_context * | ctx, | |
struct tgsi_full_instruction * | inst | |||
) | [static] |
TGSI instruction transform callback.
Replace writes to result.color w/ a temp reg. Upon END instruction, insert texture sampling code for antialiasing.
Definition at line 165 of file draw_pipe_aapoint.c.
References assert, aa_transform_context::colorOutput, aa_transform_context::colorTemp, tgsi_full_declaration::Declaration, tgsi_full_declaration::DeclarationRange, tgsi_full_dst_register::DstRegister, tgsi_transform_context::emit_declaration, tgsi_transform_context::emit_instruction, FALSE, tgsi_src_register::File, tgsi_dst_register::File, tgsi_declaration::File, tgsi_declaration_range::First, aa_transform_context::firstInstruction, tgsi_full_instruction::FullDstRegisters, tgsi_full_instruction::FullSrcRegisters, tgsi_src_register::Index, tgsi_dst_register::Index, tgsi_full_instruction::Instruction, tgsi_declaration::Interpolate, tgsi_declaration_range::Last, aa_transform_context::maxGeneric, aa_transform_context::maxInput, tgsi_src_register::Negate, tgsi_instruction::NumDstRegs, tgsi_instruction::NumSrcRegs, tgsi_instruction::Opcode, tgsi_full_declaration::Semantic, tgsi_declaration::Semantic, tgsi_declaration_semantic::SemanticIndex, tgsi_declaration_semantic::SemanticName, tgsi_full_src_register::SrcRegister, tgsi_src_register::SwizzleW, tgsi_src_register::SwizzleX, tgsi_src_register::SwizzleY, tgsi_src_register::SwizzleZ, aa_transform_context::tempsUsed, tgsi_default_full_declaration(), tgsi_default_full_instruction(), TGSI_FILE_INPUT, TGSI_FILE_OUTPUT, TGSI_FILE_TEMPORARY, TGSI_INTERPOLATE_PERSPECTIVE, TGSI_OPCODE_ADD, TGSI_OPCODE_CMP, TGSI_OPCODE_END, TGSI_OPCODE_KIL, TGSI_OPCODE_MOV, TGSI_OPCODE_MUL, TGSI_OPCODE_RCP, TGSI_OPCODE_RSQ, TGSI_OPCODE_SGT, TGSI_OPCODE_SLE, TGSI_OPCODE_SUB, TGSI_SEMANTIC_GENERIC, TGSI_SWIZZLE_W, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_WRITEMASK_W, TGSI_WRITEMASK_X, TGSI_WRITEMASK_XY, TGSI_WRITEMASK_XYZ, TGSI_WRITEMASK_Y, TGSI_WRITEMASK_Z, aa_transform_context::tmp0, and tgsi_dst_register::WriteMask.
00167 { 00168 struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; 00169 struct tgsi_full_instruction newInst; 00170 00171 if (aactx->firstInstruction) { 00172 /* emit our new declarations before the first instruction */ 00173 00174 struct tgsi_full_declaration decl; 00175 const int texInput = aactx->maxInput + 1; 00176 int tmp0; 00177 uint i; 00178 00179 /* find two free temp regs */ 00180 for (i = 0; i < 32; i++) { 00181 if ((aactx->tempsUsed & (1 << i)) == 0) { 00182 /* found a free temp */ 00183 if (aactx->tmp0 < 0) 00184 aactx->tmp0 = i; 00185 else if (aactx->colorTemp < 0) 00186 aactx->colorTemp = i; 00187 else 00188 break; 00189 } 00190 } 00191 00192 assert(aactx->colorTemp != aactx->tmp0); 00193 00194 tmp0 = aactx->tmp0; 00195 00196 /* declare new generic input/texcoord */ 00197 decl = tgsi_default_full_declaration(); 00198 decl.Declaration.File = TGSI_FILE_INPUT; 00199 /* XXX this could be linear... */ 00200 decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; 00201 decl.Declaration.Semantic = 1; 00202 decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC; 00203 decl.Semantic.SemanticIndex = aactx->maxGeneric + 1; 00204 decl.DeclarationRange.First = 00205 decl.DeclarationRange.Last = texInput; 00206 ctx->emit_declaration(ctx, &decl); 00207 00208 /* declare new temp regs */ 00209 decl = tgsi_default_full_declaration(); 00210 decl.Declaration.File = TGSI_FILE_TEMPORARY; 00211 decl.DeclarationRange.First = 00212 decl.DeclarationRange.Last = tmp0; 00213 ctx->emit_declaration(ctx, &decl); 00214 00215 decl = tgsi_default_full_declaration(); 00216 decl.Declaration.File = TGSI_FILE_TEMPORARY; 00217 decl.DeclarationRange.First = 00218 decl.DeclarationRange.Last = aactx->colorTemp; 00219 ctx->emit_declaration(ctx, &decl); 00220 00221 aactx->firstInstruction = FALSE; 00222 00223 00224 /* 00225 * Emit code to compute fragment coverage, kill if outside point radius 00226 * 00227 * Temp reg0 usage: 00228 * t0.x = distance of fragment from center point 00229 * t0.y = boolean, is t0.x > 1.0, also misc temp usage 00230 * t0.z = temporary for computing 1/(1-k) value 00231 * t0.w = final coverage value 00232 */ 00233 00234 /* MUL t0.xy, tex, tex; # compute x^2, y^2 */ 00235 newInst = tgsi_default_full_instruction(); 00236 newInst.Instruction.Opcode = TGSI_OPCODE_MUL; 00237 newInst.Instruction.NumDstRegs = 1; 00238 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00239 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00240 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XY; 00241 newInst.Instruction.NumSrcRegs = 2; 00242 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; 00243 newInst.FullSrcRegisters[0].SrcRegister.Index = texInput; 00244 newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT; 00245 newInst.FullSrcRegisters[1].SrcRegister.Index = texInput; 00246 ctx->emit_instruction(ctx, &newInst); 00247 00248 /* ADD t0.x, t0.x, t0.y; # x^2 + y^2 */ 00249 newInst = tgsi_default_full_instruction(); 00250 newInst.Instruction.Opcode = TGSI_OPCODE_ADD; 00251 newInst.Instruction.NumDstRegs = 1; 00252 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00253 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00254 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X; 00255 newInst.Instruction.NumSrcRegs = 2; 00256 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00257 newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; 00258 newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; 00259 newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY; 00260 newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0; 00261 newInst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; 00262 ctx->emit_instruction(ctx, &newInst); 00263 00264 #if NORMALIZE /* OPTIONAL normalization of length */ 00265 /* RSQ t0.x, t0.x; */ 00266 newInst = tgsi_default_full_instruction(); 00267 newInst.Instruction.Opcode = TGSI_OPCODE_RSQ; 00268 newInst.Instruction.NumDstRegs = 1; 00269 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00270 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00271 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X; 00272 newInst.Instruction.NumSrcRegs = 1; 00273 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00274 newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; 00275 ctx->emit_instruction(ctx, &newInst); 00276 00277 /* RCP t0.x, t0.x; */ 00278 newInst = tgsi_default_full_instruction(); 00279 newInst.Instruction.Opcode = TGSI_OPCODE_RCP; 00280 newInst.Instruction.NumDstRegs = 1; 00281 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00282 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00283 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X; 00284 newInst.Instruction.NumSrcRegs = 1; 00285 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00286 newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; 00287 ctx->emit_instruction(ctx, &newInst); 00288 #endif 00289 00290 /* SGT t0.y, t0.xxxx, t0.wwww; # bool b = d > 1 (NOTE t0.w == 1) */ 00291 newInst = tgsi_default_full_instruction(); 00292 newInst.Instruction.Opcode = TGSI_OPCODE_SGT; 00293 newInst.Instruction.NumDstRegs = 1; 00294 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00295 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00296 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y; 00297 newInst.Instruction.NumSrcRegs = 2; 00298 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00299 newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; 00300 newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; 00301 newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT; 00302 newInst.FullSrcRegisters[1].SrcRegister.Index = texInput; 00303 newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_W; 00304 ctx->emit_instruction(ctx, &newInst); 00305 00306 /* KIL -tmp0.yyyy; # if -tmp0.y < 0, KILL */ 00307 newInst = tgsi_default_full_instruction(); 00308 newInst.Instruction.Opcode = TGSI_OPCODE_KIL; 00309 newInst.Instruction.NumDstRegs = 0; 00310 newInst.Instruction.NumSrcRegs = 1; 00311 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00312 newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; 00313 newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; 00314 newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; 00315 newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; 00316 newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; 00317 newInst.FullSrcRegisters[0].SrcRegister.Negate = 1; 00318 ctx->emit_instruction(ctx, &newInst); 00319 00320 00321 /* compute coverage factor = (1-d)/(1-k) */ 00322 00323 /* SUB t0.z, tex.w, tex.z; # m = 1 - k */ 00324 newInst = tgsi_default_full_instruction(); 00325 newInst.Instruction.Opcode = TGSI_OPCODE_SUB; 00326 newInst.Instruction.NumDstRegs = 1; 00327 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00328 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00329 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Z; 00330 newInst.Instruction.NumSrcRegs = 2; 00331 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; 00332 newInst.FullSrcRegisters[0].SrcRegister.Index = texInput; 00333 newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W; 00334 newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT; 00335 newInst.FullSrcRegisters[1].SrcRegister.Index = texInput; 00336 newInst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z; 00337 ctx->emit_instruction(ctx, &newInst); 00338 00339 /* RCP t0.z, t0.z; # t0.z = 1 / m */ 00340 newInst = tgsi_default_full_instruction(); 00341 newInst.Instruction.Opcode = TGSI_OPCODE_RCP; 00342 newInst.Instruction.NumDstRegs = 1; 00343 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00344 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00345 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Z; 00346 newInst.Instruction.NumSrcRegs = 1; 00347 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00348 newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; 00349 newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Z; 00350 ctx->emit_instruction(ctx, &newInst); 00351 00352 /* SUB t0.y, 1, t0.x; # d = 1 - d */ 00353 newInst = tgsi_default_full_instruction(); 00354 newInst.Instruction.Opcode = TGSI_OPCODE_SUB; 00355 newInst.Instruction.NumDstRegs = 1; 00356 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00357 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00358 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y; 00359 newInst.Instruction.NumSrcRegs = 2; 00360 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; 00361 newInst.FullSrcRegisters[0].SrcRegister.Index = texInput; 00362 newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_W; 00363 newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY; 00364 newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0; 00365 newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; 00366 ctx->emit_instruction(ctx, &newInst); 00367 00368 /* MUL t0.w, t0.y, t0.z; # coverage = d * m */ 00369 newInst = tgsi_default_full_instruction(); 00370 newInst.Instruction.Opcode = TGSI_OPCODE_MUL; 00371 newInst.Instruction.NumDstRegs = 1; 00372 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00373 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00374 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W; 00375 newInst.Instruction.NumSrcRegs = 2; 00376 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00377 newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; 00378 newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; 00379 newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY; 00380 newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0; 00381 newInst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Z; 00382 ctx->emit_instruction(ctx, &newInst); 00383 00384 /* SLE t0.y, t0.x, tex.z; # bool b = distance <= k */ 00385 newInst = tgsi_default_full_instruction(); 00386 newInst.Instruction.Opcode = TGSI_OPCODE_SLE; 00387 newInst.Instruction.NumDstRegs = 1; 00388 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00389 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00390 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y; 00391 newInst.Instruction.NumSrcRegs = 2; 00392 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00393 newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; 00394 newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; 00395 newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT; 00396 newInst.FullSrcRegisters[1].SrcRegister.Index = texInput; 00397 newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Z; 00398 ctx->emit_instruction(ctx, &newInst); 00399 00400 /* CMP t0.w, -t0.y, tex.w, t0.w; 00401 * # if -t0.y < 0 then 00402 * t0.w = 1 00403 * else 00404 * t0.w = t0.w 00405 */ 00406 newInst = tgsi_default_full_instruction(); 00407 newInst.Instruction.Opcode = TGSI_OPCODE_CMP; 00408 newInst.Instruction.NumDstRegs = 1; 00409 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; 00410 newInst.FullDstRegisters[0].DstRegister.Index = tmp0; 00411 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W; 00412 newInst.Instruction.NumSrcRegs = 3; 00413 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00414 newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; 00415 newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; 00416 newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; 00417 newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; 00418 newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; 00419 newInst.FullSrcRegisters[0].SrcRegister.Negate = 1; 00420 newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT; 00421 newInst.FullSrcRegisters[1].SrcRegister.Index = texInput; 00422 newInst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_W; 00423 newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_W; 00424 newInst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W; 00425 newInst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_W; 00426 newInst.FullSrcRegisters[2].SrcRegister.File = TGSI_FILE_TEMPORARY; 00427 newInst.FullSrcRegisters[2].SrcRegister.Index = tmp0; 00428 newInst.FullSrcRegisters[2].SrcRegister.SwizzleX = TGSI_SWIZZLE_W; 00429 newInst.FullSrcRegisters[2].SrcRegister.SwizzleY = TGSI_SWIZZLE_W; 00430 newInst.FullSrcRegisters[2].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W; 00431 newInst.FullSrcRegisters[2].SrcRegister.SwizzleW = TGSI_SWIZZLE_W; 00432 ctx->emit_instruction(ctx, &newInst); 00433 00434 } 00435 00436 if (inst->Instruction.Opcode == TGSI_OPCODE_END) { 00437 /* add alpha modulation code at tail of program */ 00438 00439 /* MOV result.color.xyz, colorTemp; */ 00440 newInst = tgsi_default_full_instruction(); 00441 newInst.Instruction.Opcode = TGSI_OPCODE_MOV; 00442 newInst.Instruction.NumDstRegs = 1; 00443 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; 00444 newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput; 00445 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XYZ; 00446 newInst.Instruction.NumSrcRegs = 1; 00447 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00448 newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp; 00449 ctx->emit_instruction(ctx, &newInst); 00450 00451 /* MUL result.color.w, colorTemp, tmp0.w; */ 00452 newInst = tgsi_default_full_instruction(); 00453 newInst.Instruction.Opcode = TGSI_OPCODE_MUL; 00454 newInst.Instruction.NumDstRegs = 1; 00455 newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; 00456 newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput; 00457 newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W; 00458 newInst.Instruction.NumSrcRegs = 2; 00459 newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; 00460 newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp; 00461 newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY; 00462 newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->tmp0; 00463 ctx->emit_instruction(ctx, &newInst); 00464 } 00465 else { 00466 /* Not an END instruction. 00467 * Look for writes to result.color and replace with colorTemp reg. 00468 */ 00469 uint i; 00470 00471 for (i = 0; i < inst->Instruction.NumDstRegs; i++) { 00472 struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; 00473 if (dst->DstRegister.File == TGSI_FILE_OUTPUT && 00474 dst->DstRegister.Index == aactx->colorOutput) { 00475 dst->DstRegister.File = TGSI_FILE_TEMPORARY; 00476 dst->DstRegister.Index = aactx->colorTemp; 00477 } 00478 } 00479 } 00480 00481 ctx->emit_instruction(ctx, inst); 00482 }
static void aapoint_bind_fs_state | ( | struct pipe_context * | pipe, | |
void * | fs | |||
) | [static] |
Definition at line 810 of file draw_pipe_aapoint.c.
References aapoint_stage_from_pipe(), aapoint_stage::driver_bind_fs_state, aapoint_fragment_shader::driver_fs, aapoint_stage::fs, and aapoint_stage::pipe.
00812 { 00813 struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe); 00814 struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs; 00815 /* save current */ 00816 aapoint->fs = aafs; 00817 /* pass-through */ 00818 aapoint->driver_bind_fs_state(aapoint->pipe, 00819 (aafs ? aafs->driver_fs : NULL));
static void* aapoint_create_fs_state | ( | struct pipe_context * | pipe, | |
const struct pipe_shader_state * | fs | |||
) | [static] |
This function overrides the driver's create_fs_state() function and will typically be called by the state tracker.
Definition at line 792 of file draw_pipe_aapoint.c.
References aapoint_stage_from_pipe(), CALLOC_STRUCT, aapoint_stage::driver_create_fs_state, aapoint_fragment_shader::driver_fs, aapoint_stage::pipe, and aapoint_fragment_shader::state.
00795 { 00796 struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe); 00797 struct aapoint_fragment_shader *aafs = CALLOC_STRUCT(aapoint_fragment_shader); 00798 if (aafs == NULL) 00799 return NULL; 00800 00801 aafs->state = *fs; 00802 00803 /* pass-through */ 00804 aafs->driver_fs = aapoint->driver_create_fs_state(aapoint->pipe, fs); 00805 00806 return aafs;
static void aapoint_delete_fs_state | ( | struct pipe_context * | pipe, | |
void * | fs | |||
) | [static] |
Definition at line 823 of file draw_pipe_aapoint.c.
References aapoint_stage_from_pipe(), aapoint_stage::driver_delete_fs_state, aapoint_fragment_shader::driver_fs, FREE, and aapoint_stage::pipe.
00825 { 00826 struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe); 00827 struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs; 00828 /* pass-through */ 00829 aapoint->driver_delete_fs_state(aapoint->pipe, aafs->driver_fs); 00830 FREE(aafs);
static void aapoint_destroy | ( | struct draw_stage * | stage | ) | [static] |
Definition at line 742 of file draw_pipe_aapoint.c.
References draw_free_temp_verts(), and FREE.
00744 { 00745 draw_free_temp_verts( stage ); 00746 FREE( stage );
static void aapoint_first_point | ( | struct draw_stage * | stage, | |
struct prim_header * | header | |||
) | [static] |
Definition at line 668 of file draw_pipe_aapoint.c.
References aapoint_point(), aapoint_stage(), assert, bind_aapoint_fragment_shader(), draw_stage::draw, draw, draw_context::extra_vp_outputs, aapoint_stage::fs, aapoint_fragment_shader::generic_attrib, draw_vertex_shader::info, tgsi_shader_info::num_outputs, draw_context::num_vs_outputs, tgsi_shader_info::output_semantic_name, draw_stage::point, pipe_rasterizer_state::point_size, pipe_rasterizer_state::point_size_per_vertex, pipe_rasterizer_state::point_smooth, aapoint_stage::pos_slot, draw_context::position_output, aapoint_stage::psize_slot, aapoint_stage::radius, draw_context::rasterizer, draw_context::semantic_index, draw_context::semantic_name, draw_context::slot, aapoint_stage::tex_slot, TGSI_SEMANTIC_GENERIC, TGSI_SEMANTIC_PSIZE, draw_context::vertex_shader, and draw_context::vs.
00670 { 00671 auto struct aapoint_stage *aapoint = aapoint_stage(stage); 00672 struct draw_context *draw = stage->draw; 00673 00674 assert(draw->rasterizer->point_smooth); 00675 00676 if (draw->rasterizer->point_size <= 2.0) 00677 aapoint->radius = 1.0; 00678 else 00679 aapoint->radius = 0.5f * draw->rasterizer->point_size; 00680 00681 /* 00682 * Bind (generate) our fragprog. 00683 */ 00684 bind_aapoint_fragment_shader(aapoint); 00685 00686 /* update vertex attrib info */ 00687 aapoint->tex_slot = draw->vs.num_vs_outputs; 00688 assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */ 00689 00690 aapoint->pos_slot = draw->vs.position_output; 00691 00692 draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; 00693 draw->extra_vp_outputs.semantic_index = aapoint->fs->generic_attrib; 00694 draw->extra_vp_outputs.slot = aapoint->tex_slot; 00695 00696 /* find psize slot in post-transform vertex */ 00697 aapoint->psize_slot = -1; 00698 if (draw->rasterizer->point_size_per_vertex) { 00699 /* find PSIZ vertex output */ 00700 const struct draw_vertex_shader *vs = draw->vs.vertex_shader; 00701 uint i; 00702 for (i = 0; i < vs->info.num_outputs; i++) { 00703 if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) { 00704 aapoint->psize_slot = i; 00705 break; 00706 } 00707 } 00708 } 00709 00710 /* now really draw first point */ 00711 stage->point = aapoint_point; 00712 stage->point(stage, header);
static void aapoint_flush | ( | struct draw_stage * | stage, | |
unsigned | flags | |||
) | [static] |
Definition at line 716 of file draw_pipe_aapoint.c.
References aapoint_first_point(), aapoint_stage(), draw_stage::draw, draw, aapoint_stage::driver_bind_fs_state, aapoint_fragment_shader::driver_fs, draw_context::extra_vp_outputs, FALSE, draw_stage::flush, aapoint_stage::fs, draw_stage::next, aapoint_stage::pipe, draw_stage::point, draw_context::slot, draw_context::suspend_flushing, and TRUE.
00718 { 00719 struct draw_context *draw = stage->draw; 00720 struct aapoint_stage *aapoint = aapoint_stage(stage); 00721 struct pipe_context *pipe = aapoint->pipe; 00722 00723 stage->point = aapoint_first_point; 00724 stage->next->flush( stage->next, flags ); 00725 00726 /* restore original frag shader */ 00727 draw->suspend_flushing = TRUE; 00728 aapoint->driver_bind_fs_state(pipe, aapoint->fs->driver_fs); 00729 draw->suspend_flushing = FALSE; 00730 00731 draw->extra_vp_outputs.slot = 0;
static void aapoint_point | ( | struct draw_stage * | stage, | |
struct prim_header * | header | |||
) | [static] |
Draw an AA point by drawing a quad.
Definition at line 570 of file draw_pipe_aapoint.c.
References aapoint_stage(), ASSIGN_4V, vertex_header::data, dup_vert(), draw_stage::next, aapoint_stage::pos_slot, aapoint_stage::psize_slot, aapoint_stage::radius, aapoint_stage::tex_slot, draw_stage::tri, and prim_header::v.
00571 { 00572 const struct aapoint_stage *aapoint = aapoint_stage(stage); 00573 struct prim_header tri; 00574 struct vertex_header *v[4]; 00575 uint texPos = aapoint->tex_slot; 00576 uint pos_slot = aapoint->pos_slot; 00577 float radius, *pos, *tex; 00578 uint i; 00579 float k; 00580 00581 if (aapoint->psize_slot >= 0) { 00582 radius = 0.5f * header->v[0]->data[aapoint->psize_slot][0]; 00583 } 00584 else { 00585 radius = aapoint->radius; 00586 } 00587 00588 /* 00589 * Note: the texcoords (generic attrib, really) we use are special: 00590 * The S and T components simply vary from -1 to +1. 00591 * The R component is k, below. 00592 * The Q component is 1.0 and will used as a handy constant in the 00593 * fragment shader. 00594 */ 00595 00596 /* 00597 * k is the threshold distance from the point's center at which 00598 * we begin alpha attenuation (the coverage value). 00599 * Operating within a unit circle, we'll compute the fragment's 00600 * distance 'd' from the center point using the texcoords. 00601 * IF d > 1.0 THEN 00602 * KILL fragment 00603 * ELSE IF d > k THEN 00604 * compute coverage in [0,1] proportional to d in [k, 1]. 00605 * ELSE 00606 * coverage = 1.0; // full coverage 00607 * ENDIF 00608 * 00609 * Note: the ELSEIF and ELSE clauses are actually implemented with CMP to 00610 * avoid using IF/ELSE/ENDIF TGSI opcodes. 00611 */ 00612 00613 #if !NORMALIZE 00614 k = 1.0f / radius; 00615 k = 1.0f - 2.0f * k + k * k; 00616 #else 00617 k = 1.0f - 1.0f / radius; 00618 #endif 00619 00620 /* allocate/dup new verts */ 00621 for (i = 0; i < 4; i++) { 00622 v[i] = dup_vert(stage, header->v[0], i); 00623 } 00624 00625 /* new verts */ 00626 pos = v[0]->data[pos_slot]; 00627 pos[0] -= radius; 00628 pos[1] -= radius; 00629 00630 pos = v[1]->data[pos_slot]; 00631 pos[0] += radius; 00632 pos[1] -= radius; 00633 00634 pos = v[2]->data[pos_slot]; 00635 pos[0] += radius; 00636 pos[1] += radius; 00637 00638 pos = v[3]->data[pos_slot]; 00639 pos[0] -= radius; 00640 pos[1] += radius; 00641 00642 /* new texcoords */ 00643 tex = v[0]->data[texPos]; 00644 ASSIGN_4V(tex, -1, -1, k, 1); 00645 00646 tex = v[1]->data[texPos]; 00647 ASSIGN_4V(tex, 1, -1, k, 1); 00648 00649 tex = v[2]->data[texPos]; 00650 ASSIGN_4V(tex, 1, 1, k, 1); 00651 00652 tex = v[3]->data[texPos]; 00653 ASSIGN_4V(tex, -1, 1, k, 1); 00654 00655 /* emit 2 tris for the quad strip */ 00656 tri.v[0] = v[0]; 00657 tri.v[1] = v[1]; 00658 tri.v[2] = v[2]; 00659 stage->next->tri( stage->next, &tri ); 00660 00661 tri.v[0] = v[0]; 00662 tri.v[1] = v[2]; 00663 tri.v[2] = v[3]; 00664 stage->next->tri( stage->next, &tri );
static void aapoint_reset_stipple_counter | ( | struct draw_stage * | stage | ) | [static] |
Definition at line 735 of file draw_pipe_aapoint.c.
References draw_stage::next, and draw_stage::reset_stipple_counter.
00737 { 00738 stage->next->reset_stipple_counter( stage->next );
static struct aapoint_stage* aapoint_stage | ( | struct draw_stage * | stage | ) | [static, read] |
Definition at line 558 of file draw_pipe_aapoint.c.
00559 { 00560 return (struct aapoint_stage *) stage; 00561 }
static struct aapoint_stage* aapoint_stage_from_pipe | ( | struct pipe_context * | pipe | ) | [static, read] |
Definition at line 780 of file draw_pipe_aapoint.c.
References draw_context::aapoint, pipe_context::draw, draw, and draw_context::pipeline.
00782 { 00783 struct draw_context *draw = (struct draw_context *) pipe->draw; 00784 return aapoint_stage(draw->pipeline.aapoint);
static boolean bind_aapoint_fragment_shader | ( | struct aapoint_stage * | aapoint | ) | [static] |
When we're about to draw our first AA point in a batch, this function is called to tell the driver to bind our modified fragment shader.
Definition at line 540 of file draw_pipe_aapoint.c.
References aapoint_fragment_shader::aapoint_fs, draw_stage::draw, draw, aapoint_stage::driver_bind_fs_state, FALSE, aapoint_stage::fs, generate_aapoint_fs(), aapoint_stage::pipe, aapoint_stage::stage, draw_context::suspend_flushing, and TRUE.
00541 { 00542 struct draw_context *draw = aapoint->stage.draw; 00543 00544 if (!aapoint->fs->aapoint_fs && 00545 !generate_aapoint_fs(aapoint)) 00546 return FALSE; 00547 00548 draw->suspend_flushing = TRUE; 00549 aapoint->driver_bind_fs_state(aapoint->pipe, aapoint->fs->aapoint_fs); 00550 draw->suspend_flushing = FALSE; 00551 00552 return TRUE; 00553 }
static struct aapoint_stage* draw_aapoint_stage | ( | struct draw_context * | draw | ) | [static, read] |
Definition at line 750 of file draw_pipe_aapoint.c.
References aapoint_destroy(), aapoint_first_point(), aapoint_flush(), aapoint_reset_stipple_counter(), CALLOC_STRUCT, draw_stage::destroy, draw_stage::draw, draw_alloc_temp_verts(), draw_pipe_passthrough_line(), draw_pipe_passthrough_tri(), draw_stage::flush, draw_stage::line, draw_stage::next, draw_stage::point, draw_stage::reset_stipple_counter, aapoint_stage::stage, and draw_stage::tri.
00752 { 00753 struct aapoint_stage *aapoint = CALLOC_STRUCT(aapoint_stage); 00754 if (aapoint == NULL) 00755 goto fail; 00756 00757 if (!draw_alloc_temp_verts( &aapoint->stage, 4 )) 00758 goto fail; 00759 00760 aapoint->stage.draw = draw; 00761 aapoint->stage.next = NULL; 00762 aapoint->stage.point = aapoint_first_point; 00763 aapoint->stage.line = draw_pipe_passthrough_line; 00764 aapoint->stage.tri = draw_pipe_passthrough_tri; 00765 aapoint->stage.flush = aapoint_flush; 00766 aapoint->stage.reset_stipple_counter = aapoint_reset_stipple_counter; 00767 aapoint->stage.destroy = aapoint_destroy; 00768 00769 return aapoint; 00770 00771 fail: 00772 if (aapoint) 00773 aapoint_destroy(&aapoint->stage); 00774 00775 return NULL; 00776
boolean draw_install_aapoint_stage | ( | struct draw_context * | draw, | |
struct pipe_context * | pipe | |||
) |
Called by drivers that want to install this AA point prim stage into the draw module's pipeline.
This will not be used if the hardware has native support for AA points.
Definition at line 839 of file draw_pipe_aapoint.c.
References draw_context::aapoint, aapoint_bind_fs_state(), aapoint_create_fs_state(), aapoint_delete_fs_state(), pipe_context::bind_fs_state, pipe_context::create_fs_state, pipe_context::delete_fs_state, draw_stage::destroy, pipe_context::draw, draw_aapoint_stage(), aapoint_stage::driver_bind_fs_state, aapoint_stage::driver_create_fs_state, aapoint_stage::driver_delete_fs_state, FALSE, aapoint_stage::pipe, draw_context::pipeline, aapoint_stage::stage, and TRUE.
00842 { 00843 struct aapoint_stage *aapoint; 00844 00845 pipe->draw = (void *) draw; 00846 00847 /* 00848 * Create / install AA point drawing / prim stage 00849 */ 00850 aapoint = draw_aapoint_stage( draw ); 00851 if (aapoint == NULL) 00852 goto fail; 00853 00854 aapoint->pipe = pipe; 00855 00856 /* save original driver functions */ 00857 aapoint->driver_create_fs_state = pipe->create_fs_state; 00858 aapoint->driver_bind_fs_state = pipe->bind_fs_state; 00859 aapoint->driver_delete_fs_state = pipe->delete_fs_state; 00860 00861 /* override the driver's functions */ 00862 pipe->create_fs_state = aapoint_create_fs_state; 00863 pipe->bind_fs_state = aapoint_bind_fs_state; 00864 pipe->delete_fs_state = aapoint_delete_fs_state; 00865 00866 draw->pipeline.aapoint = &aapoint->stage; 00867 00868 return TRUE; 00869 00870 fail: 00871 if (aapoint) 00872 aapoint->stage.destroy( &aapoint->stage ); 00873 00874 return FALSE;
static boolean generate_aapoint_fs | ( | struct aapoint_stage * | aapoint | ) | [static] |
Generate the frag shader we'll use for drawing AA points.
This will be the user's shader plus some texture/modulate instructions.
Definition at line 490 of file draw_pipe_aapoint.c.
References aa_transform_decl(), aa_transform_inst(), aapoint_fragment_shader::aapoint_fs, aa_transform_context::base, aa_transform_context::colorOutput, aa_transform_context::colorTemp, aapoint_stage::driver_create_fs_state, FALSE, aa_transform_context::firstInstruction, aapoint_stage::fs, aapoint_fragment_shader::generic_attrib, MALLOC, MAX, aa_transform_context::maxGeneric, aa_transform_context::maxInput, aapoint_stage::pipe, aapoint_fragment_shader::state, tgsi_dump(), tgsi_transform_shader(), aa_transform_context::tmp0, pipe_shader_state::tokens, tgsi_transform_context::transform_declaration, tgsi_transform_context::transform_instruction, and TRUE.
00491 { 00492 const struct pipe_shader_state *orig_fs = &aapoint->fs->state; 00493 struct pipe_shader_state aapoint_fs; 00494 struct aa_transform_context transform; 00495 00496 #define MAX 1000 00497 00498 aapoint_fs = *orig_fs; /* copy to init */ 00499 aapoint_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX); 00500 if (aapoint_fs.tokens == NULL) 00501 return FALSE; 00502 00503 memset(&transform, 0, sizeof(transform)); 00504 transform.colorOutput = -1; 00505 transform.maxInput = -1; 00506 transform.maxGeneric = -1; 00507 transform.colorTemp = -1; 00508 transform.tmp0 = -1; 00509 transform.firstInstruction = TRUE; 00510 transform.base.transform_instruction = aa_transform_inst; 00511 transform.base.transform_declaration = aa_transform_decl; 00512 00513 tgsi_transform_shader(orig_fs->tokens, 00514 (struct tgsi_token *) aapoint_fs.tokens, 00515 MAX, &transform.base); 00516 00517 #if 0 /* DEBUG */ 00518 printf("draw_aapoint, orig shader:\n"); 00519 tgsi_dump(orig_fs->tokens, 0); 00520 printf("draw_aapoint, new shader:\n"); 00521 tgsi_dump(aapoint_fs.tokens, 0); 00522 #endif 00523 00524 aapoint->fs->aapoint_fs 00525 = aapoint->driver_create_fs_state(aapoint->pipe, &aapoint_fs); 00526 if (aapoint->fs->aapoint_fs == NULL) 00527 return FALSE; 00528 00529 aapoint->fs->generic_attrib = transform.maxGeneric + 1; 00530 00531 return TRUE; 00532 }