draw_pipe_aapoint.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00041 #include "pipe/p_inlines.h"
00042 #include "pipe/p_context.h"
00043 #include "pipe/p_defines.h"
00044 #include "pipe/p_shader_tokens.h"
00045 
00046 #include "tgsi/tgsi_transform.h"
00047 #include "tgsi/tgsi_dump.h"
00048 
00049 #include "util/u_math.h"
00050 #include "util/u_memory.h"
00051 
00052 #include "draw_context.h"
00053 #include "draw_vs.h"
00054 #include "draw_pipe.h"
00055 
00056 
00057 /*
00058  * Enabling NORMALIZE might give _slightly_ better results.
00059  * Basically, it controls whether we compute distance as d=sqrt(x*x+y*y) or
00060  * d=x*x+y*y.  Since we're working with a unit circle, the later seems
00061  * close enough and saves some costly instructions.
00062  */
00063 #define NORMALIZE 0
00064 
00065 
00069 struct aapoint_fragment_shader
00070 {
00071    struct pipe_shader_state state;
00072    void *driver_fs;   
00073    void *aapoint_fs;  
00074    int generic_attrib; 
00075 };
00076 
00077 
00081 struct aapoint_stage
00082 {
00083    struct draw_stage stage;
00084 
00085    int psize_slot;
00086    float radius;
00087 
00089    uint tex_slot;
00090    uint pos_slot;
00091 
00092    /*
00093     * Currently bound state
00094     */
00095    struct aapoint_fragment_shader *fs;
00096 
00097    /*
00098     * Driver interface/override functions
00099     */
00100    void * (*driver_create_fs_state)(struct pipe_context *,
00101                                     const struct pipe_shader_state *);
00102    void (*driver_bind_fs_state)(struct pipe_context *, void *);
00103    void (*driver_delete_fs_state)(struct pipe_context *, void *);
00104 
00105    struct pipe_context *pipe;
00106 };
00107 
00108 
00109 
00114 struct aa_transform_context {
00115    struct tgsi_transform_context base;
00116    uint tempsUsed;  
00117    int colorOutput; 
00118    int maxInput, maxGeneric;  
00119    int tmp0, colorTemp;  
00120    boolean firstInstruction;
00121 };
00122 
00123 
00128 static void
00129 aa_transform_decl(struct tgsi_transform_context *ctx,
00130                   struct tgsi_full_declaration *decl)
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 }
00157 
00158 
00164 static void
00165 aa_transform_inst(struct tgsi_transform_context *ctx,
00166                   struct tgsi_full_instruction *inst)
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 }
00483 
00484 
00489 static boolean
00490 generate_aapoint_fs(struct aapoint_stage *aapoint)
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 }
00533 
00534 
00539 static boolean
00540 bind_aapoint_fragment_shader(struct aapoint_stage *aapoint)
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 }
00554 
00555 
00556 
00557 static INLINE struct aapoint_stage *
00558 aapoint_stage( struct draw_stage *stage )
00559 {
00560    return (struct aapoint_stage *) stage;
00561 }
00562 
00563 
00564 
00565 
00569 static void
00570 aapoint_point(struct draw_stage *stage, struct prim_header *header)
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 );
00665 }
00666 
00667 
00668 static void
00669 aapoint_first_point(struct draw_stage *stage, struct prim_header *header)
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);
00713 }
00714 
00715 
00716 static void
00717 aapoint_flush(struct draw_stage *stage, unsigned flags)
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;
00732 }
00733 
00734 
00735 static void
00736 aapoint_reset_stipple_counter(struct draw_stage *stage)
00737 {
00738    stage->next->reset_stipple_counter( stage->next );
00739 }
00740 
00741 
00742 static void
00743 aapoint_destroy(struct draw_stage *stage)
00744 {
00745    draw_free_temp_verts( stage );
00746    FREE( stage );
00747 }
00748 
00749 
00750 static struct aapoint_stage *
00751 draw_aapoint_stage(struct draw_context *draw)
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 
00777 }
00778 
00779 
00780 static struct aapoint_stage *
00781 aapoint_stage_from_pipe(struct pipe_context *pipe)
00782 {
00783    struct draw_context *draw = (struct draw_context *) pipe->draw;
00784    return aapoint_stage(draw->pipeline.aapoint);
00785 }
00786 
00787 
00792 static void *
00793 aapoint_create_fs_state(struct pipe_context *pipe,
00794                        const struct pipe_shader_state *fs)
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;
00807 }
00808 
00809 
00810 static void
00811 aapoint_bind_fs_state(struct pipe_context *pipe, void *fs)
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));
00820 }
00821 
00822 
00823 static void
00824 aapoint_delete_fs_state(struct pipe_context *pipe, void *fs)
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);
00831 }
00832 
00833 
00839 boolean
00840 draw_install_aapoint_stage(struct draw_context *draw,
00841                            struct pipe_context *pipe)
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;
00875 }

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4