draw_pipe_aaline.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 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 
00035 #include "pipe/p_inlines.h"
00036 #include "pipe/p_context.h"
00037 #include "pipe/p_defines.h"
00038 #include "pipe/p_shader_tokens.h"
00039 #include "util/u_math.h"
00040 #include "util/u_memory.h"
00041 
00042 #include "tgsi/tgsi_transform.h"
00043 #include "tgsi/tgsi_dump.h"
00044 
00045 #include "draw_context.h"
00046 #include "draw_private.h"
00047 #include "draw_pipe.h"
00048 
00049 
00053 #define MAX_TEXTURE_LEVEL  5   /* 32 x 32 */
00054 
00055 
00059 struct aaline_fragment_shader
00060 {
00061    struct pipe_shader_state state;
00062    void *driver_fs;
00063    void *aaline_fs;
00064    void *aapoint_fs; /* not yet */
00065    void *sprite_fs; /* not yet */
00066    uint sampler_unit;
00067    int generic_attrib;  
00068 };
00069 
00070 
00074 struct aaline_stage
00075 {
00076    struct draw_stage stage;
00077 
00078    float half_line_width;
00079 
00081    uint tex_slot;
00083    uint pos_slot;
00084 
00085    void *sampler_cso;
00086    struct pipe_texture *texture;
00087    uint num_samplers;
00088    uint num_textures;
00089 
00090 
00091    /*
00092     * Currently bound state
00093     */
00094    struct aaline_fragment_shader *fs;
00095    struct {
00096       void *sampler[PIPE_MAX_SAMPLERS];
00097       struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
00098    } state;
00099 
00100    /*
00101     * Driver interface/override functions
00102     */
00103    void * (*driver_create_fs_state)(struct pipe_context *,
00104                                     const struct pipe_shader_state *);
00105    void (*driver_bind_fs_state)(struct pipe_context *, void *);
00106    void (*driver_delete_fs_state)(struct pipe_context *, void *);
00107 
00108    void (*driver_bind_sampler_states)(struct pipe_context *, unsigned,
00109                                       void **);
00110    void (*driver_set_sampler_textures)(struct pipe_context *, unsigned,
00111                                        struct pipe_texture **);
00112 
00113    struct pipe_context *pipe;
00114 };
00115 
00116 
00117 
00122 struct aa_transform_context {
00123    struct tgsi_transform_context base;
00124    uint tempsUsed;  
00125    int colorOutput; 
00126    uint samplersUsed;  
00127    int freeSampler;  
00128    int maxInput, maxGeneric;  
00129    int colorTemp, texTemp;  
00130    boolean firstInstruction;
00131 };
00132 
00133 
00138 static void
00139 aa_transform_decl(struct tgsi_transform_context *ctx,
00140                   struct tgsi_full_declaration *decl)
00141 {
00142    struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
00143 
00144    if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
00145        decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR &&
00146        decl->Semantic.SemanticIndex == 0) {
00147       aactx->colorOutput = decl->DeclarationRange.First;
00148    }
00149    else if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
00150       uint i;
00151       for (i = decl->DeclarationRange.First;
00152            i <= decl->DeclarationRange.Last; i++) {
00153          aactx->samplersUsed |= 1 << i;
00154       }
00155    }
00156    else if (decl->Declaration.File == TGSI_FILE_INPUT) {
00157       if ((int) decl->DeclarationRange.Last > aactx->maxInput)
00158          aactx->maxInput = decl->DeclarationRange.Last;
00159       if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC &&
00160            (int) decl->Semantic.SemanticIndex > aactx->maxGeneric) {
00161          aactx->maxGeneric = decl->Semantic.SemanticIndex;
00162       }
00163    }
00164    else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
00165       uint i;
00166       for (i = decl->DeclarationRange.First;
00167            i <= decl->DeclarationRange.Last; i++) {
00168          aactx->tempsUsed |= (1 << i);
00169       }
00170    }
00171 
00172    ctx->emit_declaration(ctx, decl);
00173 }
00174 
00175 
00179 static int
00180 free_bit(uint bitfield)
00181 {
00182    int i;
00183    for (i = 0; i < 32; i++) {
00184       if ((bitfield & (1 << i)) == 0)
00185          return i;
00186    }
00187    return -1;
00188 }
00189 
00190 
00196 static void
00197 aa_transform_inst(struct tgsi_transform_context *ctx,
00198                   struct tgsi_full_instruction *inst)
00199 {
00200    struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
00201 
00202    if (aactx->firstInstruction) {
00203       /* emit our new declarations before the first instruction */
00204 
00205       struct tgsi_full_declaration decl;
00206       uint i;
00207 
00208       /* find free sampler */
00209       aactx->freeSampler = free_bit(aactx->samplersUsed);
00210       if (aactx->freeSampler >= PIPE_MAX_SAMPLERS)
00211          aactx->freeSampler = PIPE_MAX_SAMPLERS - 1;
00212 
00213       /* find two free temp regs */
00214       for (i = 0; i < 32; i++) {
00215          if ((aactx->tempsUsed & (1 << i)) == 0) {
00216             /* found a free temp */
00217             if (aactx->colorTemp < 0)
00218                aactx->colorTemp  = i;
00219             else if (aactx->texTemp < 0)
00220                aactx->texTemp  = i;
00221             else
00222                break;
00223          }
00224       }
00225       assert(aactx->colorTemp >= 0);
00226       assert(aactx->texTemp >= 0);
00227 
00228       /* declare new generic input/texcoord */
00229       decl = tgsi_default_full_declaration();
00230       decl.Declaration.File = TGSI_FILE_INPUT;
00231       /* XXX this could be linear... */
00232       decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
00233       decl.Declaration.Semantic = 1;
00234       decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
00235       decl.Semantic.SemanticIndex = aactx->maxGeneric + 1;
00236       decl.DeclarationRange.First = 
00237       decl.DeclarationRange.Last = aactx->maxInput + 1;
00238       ctx->emit_declaration(ctx, &decl);
00239 
00240       /* declare new sampler */
00241       decl = tgsi_default_full_declaration();
00242       decl.Declaration.File = TGSI_FILE_SAMPLER;
00243       decl.DeclarationRange.First = 
00244       decl.DeclarationRange.Last = aactx->freeSampler;
00245       ctx->emit_declaration(ctx, &decl);
00246 
00247       /* declare new temp regs */
00248       decl = tgsi_default_full_declaration();
00249       decl.Declaration.File = TGSI_FILE_TEMPORARY;
00250       decl.DeclarationRange.First = 
00251       decl.DeclarationRange.Last = aactx->texTemp;
00252       ctx->emit_declaration(ctx, &decl);
00253 
00254       decl = tgsi_default_full_declaration();
00255       decl.Declaration.File = TGSI_FILE_TEMPORARY;
00256       decl.DeclarationRange.First = 
00257       decl.DeclarationRange.Last = aactx->colorTemp;
00258       ctx->emit_declaration(ctx, &decl);
00259 
00260       aactx->firstInstruction = FALSE;
00261    }
00262 
00263    if (inst->Instruction.Opcode == TGSI_OPCODE_END &&
00264        aactx->colorOutput != -1) {
00265       struct tgsi_full_instruction newInst;
00266 
00267       /* TEX */
00268       newInst = tgsi_default_full_instruction();
00269       newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
00270       newInst.Instruction.NumDstRegs = 1;
00271       newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
00272       newInst.FullDstRegisters[0].DstRegister.Index = aactx->texTemp;
00273       newInst.Instruction.NumSrcRegs = 2;
00274       newInst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
00275       newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
00276       newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->maxInput + 1;
00277       newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
00278       newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->freeSampler;
00279 
00280       ctx->emit_instruction(ctx, &newInst);
00281 
00282       /* MOV rgb */
00283       newInst = tgsi_default_full_instruction();
00284       newInst.Instruction.Opcode = TGSI_OPCODE_MOV;
00285       newInst.Instruction.NumDstRegs = 1;
00286       newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
00287       newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
00288       newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XYZ;
00289       newInst.Instruction.NumSrcRegs = 1;
00290       newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
00291       newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
00292       ctx->emit_instruction(ctx, &newInst);
00293 
00294       /* MUL alpha */
00295       newInst = tgsi_default_full_instruction();
00296       newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
00297       newInst.Instruction.NumDstRegs = 1;
00298       newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
00299       newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
00300       newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
00301       newInst.Instruction.NumSrcRegs = 2;
00302       newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
00303       newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
00304       newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
00305       newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->texTemp;
00306       ctx->emit_instruction(ctx, &newInst);
00307 
00308       /* END */
00309       newInst = tgsi_default_full_instruction();
00310       newInst.Instruction.Opcode = TGSI_OPCODE_END;
00311       newInst.Instruction.NumDstRegs = 0;
00312       newInst.Instruction.NumSrcRegs = 0;
00313       ctx->emit_instruction(ctx, &newInst);
00314    }
00315    else {
00316       /* Not an END instruction.
00317        * Look for writes to result.color and replace with colorTemp reg.
00318        */
00319       uint i;
00320 
00321       for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
00322          struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
00323          if (dst->DstRegister.File == TGSI_FILE_OUTPUT &&
00324              dst->DstRegister.Index == aactx->colorOutput) {
00325             dst->DstRegister.File = TGSI_FILE_TEMPORARY;
00326             dst->DstRegister.Index = aactx->colorTemp;
00327          }
00328       }
00329 
00330       ctx->emit_instruction(ctx, inst);
00331    }
00332 }
00333 
00334 
00339 static boolean
00340 generate_aaline_fs(struct aaline_stage *aaline)
00341 {
00342    const struct pipe_shader_state *orig_fs = &aaline->fs->state;
00343    struct pipe_shader_state aaline_fs;
00344    struct aa_transform_context transform;
00345 
00346 #define MAX 1000
00347 
00348    aaline_fs = *orig_fs; /* copy to init */
00349    aaline_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
00350    if (aaline_fs.tokens == NULL)
00351       return FALSE;
00352 
00353    memset(&transform, 0, sizeof(transform));
00354    transform.colorOutput = -1;
00355    transform.maxInput = -1;
00356    transform.maxGeneric = -1;
00357    transform.colorTemp = -1;
00358    transform.texTemp = -1;
00359    transform.firstInstruction = TRUE;
00360    transform.base.transform_instruction = aa_transform_inst;
00361    transform.base.transform_declaration = aa_transform_decl;
00362 
00363    tgsi_transform_shader(orig_fs->tokens,
00364                          (struct tgsi_token *) aaline_fs.tokens,
00365                          MAX, &transform.base);
00366 
00367 #if 0 /* DEBUG */
00368    tgsi_dump(orig_fs->tokens, 0);
00369    tgsi_dump(aaline_fs.tokens, 0);
00370 #endif
00371 
00372    aaline->fs->sampler_unit = transform.freeSampler;
00373 
00374    aaline->fs->aaline_fs
00375       = aaline->driver_create_fs_state(aaline->pipe, &aaline_fs);
00376    if (aaline->fs->aaline_fs == NULL)
00377       return FALSE;
00378 
00379    aaline->fs->generic_attrib = transform.maxGeneric + 1;
00380    return TRUE;
00381 }
00382 
00383 
00387 static boolean
00388 aaline_create_texture(struct aaline_stage *aaline)
00389 {
00390    struct pipe_context *pipe = aaline->pipe;
00391    struct pipe_screen *screen = pipe->screen;
00392    struct pipe_texture texTemp;
00393    uint level;
00394 
00395    memset(&texTemp, 0, sizeof(texTemp));
00396    texTemp.target = PIPE_TEXTURE_2D;
00397    texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
00398    texTemp.last_level = MAX_TEXTURE_LEVEL;
00399    texTemp.width[0] = 1 << MAX_TEXTURE_LEVEL;
00400    texTemp.height[0] = 1 << MAX_TEXTURE_LEVEL;
00401    texTemp.depth[0] = 1;
00402    pf_get_block(texTemp.format, &texTemp.block);
00403 
00404    aaline->texture = screen->texture_create(screen, &texTemp);
00405    if (!aaline->texture)
00406       return FALSE;
00407 
00408    /* Fill in mipmap images.
00409     * Basically each level is solid opaque, except for the outermost
00410     * texels which are zero.  Special case the 1x1 and 2x2 levels.
00411     */
00412    for (level = 0; level <= MAX_TEXTURE_LEVEL; level++) {
00413       struct pipe_surface *surface;
00414       const uint size = aaline->texture->width[level];
00415       ubyte *data;
00416       uint i, j;
00417 
00418       assert(aaline->texture->width[level] == aaline->texture->height[level]);
00419 
00420       /* This texture is new, no need to flush. 
00421        */
00422       surface = screen->get_tex_surface(screen, aaline->texture, 0, level, 0,
00423                                         PIPE_BUFFER_USAGE_CPU_WRITE);
00424       data = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_WRITE);
00425       if (data == NULL)
00426          return FALSE;
00427 
00428       for (i = 0; i < size; i++) {
00429          for (j = 0; j < size; j++) {
00430             ubyte d;
00431             if (size == 1) {
00432                d = 255;
00433             }
00434             else if (size == 2) {
00435                d = 200; /* tuneable */
00436             }
00437             else if (i == 0 || j == 0 || i == size - 1 || j == size - 1) {
00438                d = 0;
00439             }
00440             else {
00441                d = 255;
00442             }
00443             data[i * surface->stride + j] = d;
00444          }
00445       }
00446 
00447       /* unmap */
00448       screen->surface_unmap(screen, surface);
00449       screen->tex_surface_release(screen, &surface);
00450    }
00451    return TRUE;
00452 }
00453 
00454 
00460 static boolean
00461 aaline_create_sampler(struct aaline_stage *aaline)
00462 {
00463    struct pipe_sampler_state sampler;
00464    struct pipe_context *pipe = aaline->pipe;
00465 
00466    memset(&sampler, 0, sizeof(sampler));
00467    sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
00468    sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
00469    sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
00470    sampler.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR;
00471    sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
00472    sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
00473    sampler.normalized_coords = 1;
00474    sampler.min_lod = 0.0f;
00475    sampler.max_lod = MAX_TEXTURE_LEVEL;
00476 
00477    aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
00478    if (aaline->sampler_cso == NULL)
00479       return FALSE;
00480 
00481    return TRUE;
00482 }
00483 
00484 
00489 static boolean
00490 bind_aaline_fragment_shader(struct aaline_stage *aaline)
00491 {
00492    struct draw_context *draw = aaline->stage.draw;
00493 
00494    if (!aaline->fs->aaline_fs && 
00495        !generate_aaline_fs(aaline))
00496       return FALSE;
00497 
00498    draw->suspend_flushing = TRUE;
00499    aaline->driver_bind_fs_state(aaline->pipe, aaline->fs->aaline_fs);
00500    draw->suspend_flushing = FALSE;
00501 
00502    return TRUE;
00503 }
00504 
00505 
00506 
00507 static INLINE struct aaline_stage *
00508 aaline_stage( struct draw_stage *stage )
00509 {
00510    return (struct aaline_stage *) stage;
00511 }
00512 
00513 
00518 static void
00519 aaline_line(struct draw_stage *stage, struct prim_header *header)
00520 {
00521    const struct aaline_stage *aaline = aaline_stage(stage);
00522    const float half_width = aaline->half_line_width;
00523    struct prim_header tri;
00524    struct vertex_header *v[8];
00525    uint texPos = aaline->tex_slot;
00526    uint posPos = aaline->pos_slot;
00527    float *pos, *tex;
00528    float dx = header->v[1]->data[posPos][0] - header->v[0]->data[posPos][0];
00529    float dy = header->v[1]->data[posPos][1] - header->v[0]->data[posPos][1];
00530    double a = atan2(dy, dx);
00531    float c_a = (float) cos(a), s_a = (float) sin(a);
00532    uint i;
00533 
00534    /* XXX the ends of lines aren't quite perfect yet, but probably passable */
00535    dx = 0.5F * half_width;
00536    dy = half_width;
00537 
00538    /* allocate/dup new verts */
00539    for (i = 0; i < 8; i++) {
00540       v[i] = dup_vert(stage, header->v[i/4], i);
00541    }
00542 
00543    /*
00544     * Quad strip for line from v0 to v1 (*=endpoints):
00545     *
00546     *  1   3                     5   7
00547     *  +---+---------------------+---+
00548     *  |                             |
00549     *  | *v0                     v1* |
00550     *  |                             |
00551     *  +---+---------------------+---+
00552     *  0   2                     4   6
00553     */
00554 
00555    /* new verts */
00556    pos = v[0]->data[posPos];
00557    pos[0] += (-dx * c_a -  dy * s_a);
00558    pos[1] += (-dx * s_a +  dy * c_a);
00559 
00560    pos = v[1]->data[posPos];
00561    pos[0] += (-dx * c_a - -dy * s_a);
00562    pos[1] += (-dx * s_a + -dy * c_a);
00563 
00564    pos = v[2]->data[posPos];
00565    pos[0] += ( dx * c_a -  dy * s_a);
00566    pos[1] += ( dx * s_a +  dy * c_a);
00567 
00568    pos = v[3]->data[posPos];
00569    pos[0] += ( dx * c_a - -dy * s_a);
00570    pos[1] += ( dx * s_a + -dy * c_a);
00571 
00572    pos = v[4]->data[posPos];
00573    pos[0] += (-dx * c_a -  dy * s_a);
00574    pos[1] += (-dx * s_a +  dy * c_a);
00575 
00576    pos = v[5]->data[posPos];
00577    pos[0] += (-dx * c_a - -dy * s_a);
00578    pos[1] += (-dx * s_a + -dy * c_a);
00579 
00580    pos = v[6]->data[posPos];
00581    pos[0] += ( dx * c_a -  dy * s_a);
00582    pos[1] += ( dx * s_a +  dy * c_a);
00583 
00584    pos = v[7]->data[posPos];
00585    pos[0] += ( dx * c_a - -dy * s_a);
00586    pos[1] += ( dx * s_a + -dy * c_a);
00587 
00588    /* new texcoords */
00589    tex = v[0]->data[texPos];
00590    ASSIGN_4V(tex, 0, 0, 0, 1);
00591 
00592    tex = v[1]->data[texPos];
00593    ASSIGN_4V(tex, 0, 1, 0, 1);
00594 
00595    tex = v[2]->data[texPos];
00596    ASSIGN_4V(tex, .5, 0, 0, 1);
00597 
00598    tex = v[3]->data[texPos];
00599    ASSIGN_4V(tex, .5, 1, 0, 1);
00600 
00601    tex = v[4]->data[texPos];
00602    ASSIGN_4V(tex, .5, 0, 0, 1);
00603 
00604    tex = v[5]->data[texPos];
00605    ASSIGN_4V(tex, .5, 1, 0, 1);
00606 
00607    tex = v[6]->data[texPos];
00608    ASSIGN_4V(tex, 1, 0, 0, 1);
00609 
00610    tex = v[7]->data[texPos];
00611    ASSIGN_4V(tex, 1, 1, 0, 1);
00612 
00613    /* emit 6 tris for the quad strip */
00614    tri.v[0] = v[2];  tri.v[1] = v[1];  tri.v[2] = v[0];
00615    stage->next->tri( stage->next, &tri );
00616 
00617    tri.v[0] = v[3];  tri.v[1] = v[1];  tri.v[2] = v[2];
00618    stage->next->tri( stage->next, &tri );
00619 
00620    tri.v[0] = v[4];  tri.v[1] = v[3];  tri.v[2] = v[2];
00621    stage->next->tri( stage->next, &tri );
00622 
00623    tri.v[0] = v[5];  tri.v[1] = v[3];  tri.v[2] = v[4];
00624    stage->next->tri( stage->next, &tri );
00625 
00626    tri.v[0] = v[6];  tri.v[1] = v[5];  tri.v[2] = v[4];
00627    stage->next->tri( stage->next, &tri );
00628 
00629    tri.v[0] = v[7];  tri.v[1] = v[5];  tri.v[2] = v[6];
00630    stage->next->tri( stage->next, &tri );
00631 }
00632 
00633 
00634 static void
00635 aaline_first_line(struct draw_stage *stage, struct prim_header *header)
00636 {
00637    auto struct aaline_stage *aaline = aaline_stage(stage);
00638    struct draw_context *draw = stage->draw;
00639    struct pipe_context *pipe = aaline->pipe;
00640    uint num_samplers;
00641 
00642    assert(draw->rasterizer->line_smooth);
00643 
00644    if (draw->rasterizer->line_width <= 3.0)
00645       aaline->half_line_width = 1.5f;
00646    else
00647       aaline->half_line_width = 0.5f * draw->rasterizer->line_width;
00648 
00649    /*
00650     * Bind (generate) our fragprog, sampler and texture
00651     */
00652    if (!bind_aaline_fragment_shader(aaline)) {
00653       stage->line = draw_pipe_passthrough_line;
00654       stage->line(stage, header);
00655       return;
00656    }
00657 
00658    /* update vertex attrib info */
00659    aaline->tex_slot = draw->vs.num_vs_outputs;
00660    aaline->pos_slot = draw->vs.position_output;
00661 
00662    /* advertise the extra post-transformed vertex attribute */
00663    draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
00664    draw->extra_vp_outputs.semantic_index = aaline->fs->generic_attrib;
00665    draw->extra_vp_outputs.slot = aaline->tex_slot;
00666 
00667    /* how many samplers? */
00668    /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
00669    num_samplers = MAX2(aaline->num_textures, aaline->num_samplers);
00670    num_samplers = MAX2(num_samplers, aaline->fs->sampler_unit + 1);
00671 
00672    aaline->state.sampler[aaline->fs->sampler_unit] = aaline->sampler_cso;
00673    pipe_texture_reference(&aaline->state.texture[aaline->fs->sampler_unit],
00674                           aaline->texture);
00675 
00676    draw->suspend_flushing = TRUE;
00677    aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler);
00678    aaline->driver_set_sampler_textures(pipe, num_samplers, aaline->state.texture);
00679    draw->suspend_flushing = FALSE;
00680 
00681    /* now really draw first line */
00682    stage->line = aaline_line;
00683    stage->line(stage, header);
00684 }
00685 
00686 
00687 static void
00688 aaline_flush(struct draw_stage *stage, unsigned flags)
00689 {
00690    struct draw_context *draw = stage->draw;
00691    struct aaline_stage *aaline = aaline_stage(stage);
00692    struct pipe_context *pipe = aaline->pipe;
00693 
00694    stage->line = aaline_first_line;
00695    stage->next->flush( stage->next, flags );
00696 
00697    /* restore original frag shader, texture, sampler state */
00698    draw->suspend_flushing = TRUE;
00699    aaline->driver_bind_fs_state(pipe, aaline->fs->driver_fs);
00700    aaline->driver_bind_sampler_states(pipe, aaline->num_samplers,
00701                                       aaline->state.sampler);
00702    aaline->driver_set_sampler_textures(pipe, aaline->num_textures,
00703                                        aaline->state.texture);
00704    draw->suspend_flushing = FALSE;
00705 
00706    draw->extra_vp_outputs.slot = 0;
00707 }
00708 
00709 
00710 static void
00711 aaline_reset_stipple_counter(struct draw_stage *stage)
00712 {
00713    stage->next->reset_stipple_counter( stage->next );
00714 }
00715 
00716 
00717 static void
00718 aaline_destroy(struct draw_stage *stage)
00719 {
00720    struct aaline_stage *aaline = aaline_stage(stage);
00721    uint i;
00722 
00723    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
00724       pipe_texture_reference(&aaline->state.texture[i], NULL);
00725    }
00726 
00727    if (aaline->sampler_cso)
00728       aaline->pipe->delete_sampler_state(aaline->pipe, aaline->sampler_cso);
00729 
00730    if (aaline->texture)
00731       pipe_texture_release(&aaline->texture);
00732 
00733    draw_free_temp_verts( stage );
00734 
00735    FREE( stage );
00736 }
00737 
00738 
00739 static struct aaline_stage *
00740 draw_aaline_stage(struct draw_context *draw)
00741 {
00742    struct aaline_stage *aaline = CALLOC_STRUCT(aaline_stage);
00743    if (aaline == NULL)
00744       return NULL;
00745 
00746    if (!draw_alloc_temp_verts( &aaline->stage, 8 ))
00747       goto fail;
00748 
00749    aaline->stage.draw = draw;
00750    aaline->stage.next = NULL;
00751    aaline->stage.point = draw_pipe_passthrough_point;
00752    aaline->stage.line = aaline_first_line;
00753    aaline->stage.tri = draw_pipe_passthrough_tri;
00754    aaline->stage.flush = aaline_flush;
00755    aaline->stage.reset_stipple_counter = aaline_reset_stipple_counter;
00756    aaline->stage.destroy = aaline_destroy;
00757 
00758    return aaline;
00759 
00760  fail:
00761    if (aaline)
00762       aaline_destroy(&aaline->stage);
00763 
00764    return NULL;
00765 }
00766 
00767 
00768 static struct aaline_stage *
00769 aaline_stage_from_pipe(struct pipe_context *pipe)
00770 {
00771    struct draw_context *draw = (struct draw_context *) pipe->draw;
00772    return aaline_stage(draw->pipeline.aaline);
00773 }
00774 
00775 
00780 static void *
00781 aaline_create_fs_state(struct pipe_context *pipe,
00782                        const struct pipe_shader_state *fs)
00783 {
00784    struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
00785    struct aaline_fragment_shader *aafs = CALLOC_STRUCT(aaline_fragment_shader);
00786    if (aafs == NULL)
00787       return NULL;
00788 
00789    aafs->state = *fs;
00790 
00791    /* pass-through */
00792    aafs->driver_fs = aaline->driver_create_fs_state(aaline->pipe, fs);
00793 
00794    return aafs;
00795 }
00796 
00797 
00798 static void
00799 aaline_bind_fs_state(struct pipe_context *pipe, void *fs)
00800 {
00801    struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
00802    struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
00803 
00804    /* save current */
00805    aaline->fs = aafs;
00806    /* pass-through */
00807    aaline->driver_bind_fs_state(aaline->pipe,
00808                                 (aafs ? aafs->driver_fs : NULL));
00809 }
00810 
00811 
00812 static void
00813 aaline_delete_fs_state(struct pipe_context *pipe, void *fs)
00814 {
00815    struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
00816    struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
00817    /* pass-through */
00818    aaline->driver_delete_fs_state(aaline->pipe, aafs->driver_fs);
00819    FREE(aafs);
00820 }
00821 
00822 
00823 static void
00824 aaline_bind_sampler_states(struct pipe_context *pipe,
00825                            unsigned num, void **sampler)
00826 {
00827    struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
00828 
00829    /* save current */
00830    memcpy(aaline->state.sampler, sampler, num * sizeof(void *));
00831    aaline->num_samplers = num;
00832 
00833    /* pass-through */
00834    aaline->driver_bind_sampler_states(aaline->pipe, num, sampler);
00835 }
00836 
00837 
00838 static void
00839 aaline_set_sampler_textures(struct pipe_context *pipe,
00840                             unsigned num, struct pipe_texture **texture)
00841 {
00842    struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
00843    uint i;
00844 
00845    /* save current */
00846    for (i = 0; i < num; i++) {
00847       pipe_texture_reference(&aaline->state.texture[i], texture[i]);
00848    }
00849    for ( ; i < PIPE_MAX_SAMPLERS; i++) {
00850       pipe_texture_reference(&aaline->state.texture[i], NULL);
00851    }
00852    aaline->num_textures = num;
00853 
00854    /* pass-through */
00855    aaline->driver_set_sampler_textures(aaline->pipe, num, texture);
00856 }
00857 
00858 
00864 boolean
00865 draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe)
00866 {
00867    struct aaline_stage *aaline;
00868 
00869    pipe->draw = (void *) draw;
00870 
00871    /*
00872     * Create / install AA line drawing / prim stage
00873     */
00874    aaline = draw_aaline_stage( draw );
00875    if (!aaline)
00876       goto fail;
00877 
00878    aaline->pipe = pipe;
00879 
00880    /* create special texture, sampler state */
00881    if (!aaline_create_texture(aaline))
00882       goto fail;
00883 
00884    if (!aaline_create_sampler(aaline))
00885       goto fail;
00886 
00887    /* save original driver functions */
00888    aaline->driver_create_fs_state = pipe->create_fs_state;
00889    aaline->driver_bind_fs_state = pipe->bind_fs_state;
00890    aaline->driver_delete_fs_state = pipe->delete_fs_state;
00891 
00892    aaline->driver_bind_sampler_states = pipe->bind_sampler_states;
00893    aaline->driver_set_sampler_textures = pipe->set_sampler_textures;
00894 
00895    /* override the driver's functions */
00896    pipe->create_fs_state = aaline_create_fs_state;
00897    pipe->bind_fs_state = aaline_bind_fs_state;
00898    pipe->delete_fs_state = aaline_delete_fs_state;
00899 
00900    pipe->bind_sampler_states = aaline_bind_sampler_states;
00901    pipe->set_sampler_textures = aaline_set_sampler_textures;
00902    
00903    /* Install once everything is known to be OK:
00904     */
00905    draw->pipeline.aaline = &aaline->stage;
00906 
00907    return TRUE;
00908 
00909  fail:
00910    if (aaline)
00911       aaline->stage.destroy( &aaline->stage );
00912    
00913    return FALSE;
00914 }

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