draw_pipe_pstipple.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 
00037 #include "pipe/p_inlines.h"
00038 #include "pipe/p_context.h"
00039 #include "pipe/p_defines.h"
00040 #include "pipe/p_shader_tokens.h"
00041 
00042 #include "util/u_math.h"
00043 #include "util/u_memory.h"
00044 
00045 #include "tgsi/tgsi_transform.h"
00046 #include "tgsi/tgsi_dump.h"
00047 
00048 #include "draw_context.h"
00049 #include "draw_pipe.h"
00050 
00051 
00052 
00056 struct pstip_fragment_shader
00057 {
00058    struct pipe_shader_state state;
00059    void *driver_fs;
00060    void *pstip_fs;
00061    uint sampler_unit;
00062 };
00063 
00064 
00068 struct pstip_stage
00069 {
00070    struct draw_stage stage;
00071 
00072    void *sampler_cso;
00073    struct pipe_texture *texture;
00074    uint num_samplers;
00075    uint num_textures;
00076 
00077    /*
00078     * Currently bound state
00079     */
00080    struct pstip_fragment_shader *fs;
00081    struct {
00082       void *samplers[PIPE_MAX_SAMPLERS];
00083       struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
00084       const struct pipe_poly_stipple *stipple;
00085    } state;
00086 
00087    /*
00088     * Driver interface/override functions
00089     */
00090    void * (*driver_create_fs_state)(struct pipe_context *,
00091                                     const struct pipe_shader_state *);
00092    void (*driver_bind_fs_state)(struct pipe_context *, void *);
00093    void (*driver_delete_fs_state)(struct pipe_context *, void *);
00094 
00095    void (*driver_bind_sampler_states)(struct pipe_context *, unsigned, void **);
00096 
00097    void (*driver_set_sampler_textures)(struct pipe_context *, unsigned,
00098                                        struct pipe_texture **);
00099 
00100    void (*driver_set_polygon_stipple)(struct pipe_context *,
00101                                       const struct pipe_poly_stipple *);
00102 
00103    struct pipe_context *pipe;
00104 };
00105 
00106 
00107 
00112 struct pstip_transform_context {
00113    struct tgsi_transform_context base;
00114    uint tempsUsed;  
00115    int wincoordInput;
00116    int maxInput;
00117    uint samplersUsed;  
00118    int freeSampler;  
00119    int texTemp;  
00120    int numImmed;
00121    boolean firstInstruction;
00122 };
00123 
00124 
00129 static void
00130 pstip_transform_decl(struct tgsi_transform_context *ctx,
00131                      struct tgsi_full_declaration *decl)
00132 {
00133    struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
00134 
00135    if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
00136       uint i;
00137       for (i = decl->DeclarationRange.First;
00138            i <= decl->DeclarationRange.Last; i++) {
00139          pctx->samplersUsed |= 1 << i;
00140       }
00141    }
00142    else if (decl->Declaration.File == TGSI_FILE_INPUT) {
00143       pctx->maxInput = MAX2(pctx->maxInput, (int) decl->DeclarationRange.Last);
00144       if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION)
00145          pctx->wincoordInput = (int) decl->DeclarationRange.First;
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          pctx->tempsUsed |= (1 << i);
00152       }
00153    }
00154 
00155    ctx->emit_declaration(ctx, decl);
00156 }
00157 
00158 
00159 static void
00160 pstip_transform_immed(struct tgsi_transform_context *ctx,
00161                       struct tgsi_full_immediate *immed)
00162 {
00163    struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
00164    pctx->numImmed++;
00165 }
00166 
00167 
00171 static int
00172 free_bit(uint bitfield)
00173 {
00174    int i;
00175    for (i = 0; i < 32; i++) {
00176       if ((bitfield & (1 << i)) == 0)
00177          return i;
00178    }
00179    return -1;
00180 }
00181 
00182 
00188 static void
00189 pstip_transform_inst(struct tgsi_transform_context *ctx,
00190                      struct tgsi_full_instruction *inst)
00191 {
00192    struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
00193 
00194    if (pctx->firstInstruction) {
00195       /* emit our new declarations before the first instruction */
00196 
00197       struct tgsi_full_declaration decl;
00198       struct tgsi_full_instruction newInst;
00199       uint i;
00200       int wincoordInput;
00201 
00202       /* find free sampler */
00203       pctx->freeSampler = free_bit(pctx->samplersUsed);
00204       if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
00205          pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
00206 
00207       if (pctx->wincoordInput < 0)
00208          wincoordInput = pctx->maxInput + 1;
00209       else
00210          wincoordInput = pctx->wincoordInput;
00211 
00212       /* find one free temp reg */
00213       for (i = 0; i < 32; i++) {
00214          if ((pctx->tempsUsed & (1 << i)) == 0) {
00215             /* found a free temp */
00216             if (pctx->texTemp < 0)
00217                pctx->texTemp  = i;
00218             else
00219                break;
00220          }
00221       }
00222       assert(pctx->texTemp >= 0);
00223 
00224       if (pctx->wincoordInput < 0) {
00225          /* declare new position input reg */
00226          decl = tgsi_default_full_declaration();
00227          decl.Declaration.File = TGSI_FILE_INPUT;
00228          decl.Declaration.Interpolate = TGSI_INTERPOLATE_LINEAR; /* XXX? */
00229          decl.Declaration.Semantic = 1;
00230          decl.Semantic.SemanticName = TGSI_SEMANTIC_POSITION;
00231          decl.Semantic.SemanticIndex = 0;
00232          decl.DeclarationRange.First = 
00233             decl.DeclarationRange.Last = wincoordInput;
00234          ctx->emit_declaration(ctx, &decl);
00235       }
00236 
00237       /* declare new sampler */
00238       decl = tgsi_default_full_declaration();
00239       decl.Declaration.File = TGSI_FILE_SAMPLER;
00240       decl.DeclarationRange.First = 
00241       decl.DeclarationRange.Last = pctx->freeSampler;
00242       ctx->emit_declaration(ctx, &decl);
00243 
00244       /* declare new temp regs */
00245       decl = tgsi_default_full_declaration();
00246       decl.Declaration.File = TGSI_FILE_TEMPORARY;
00247       decl.DeclarationRange.First = 
00248       decl.DeclarationRange.Last = pctx->texTemp;
00249       ctx->emit_declaration(ctx, &decl);
00250 
00251       /* emit immediate = {1/32, 1/32, 1, 1}
00252        * The index/position of this immediate will be pctx->numImmed
00253        */
00254       {
00255          static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 };
00256          struct tgsi_full_immediate immed;
00257          uint size = 4;
00258          immed = tgsi_default_full_immediate();
00259          immed.Immediate.Size = 1 + size; /* one for the token itself */
00260          immed.u.Pointer = (void *) value;
00261          ctx->emit_immediate(ctx, &immed);
00262       }
00263 
00264       pctx->firstInstruction = FALSE;
00265 
00266 
00267       /* 
00268        * Insert new MUL/TEX/KILP instructions at start of program
00269        * Take gl_FragCoord, divide by 32 (stipple size), sample the
00270        * texture and kill fragment if needed.
00271        *
00272        * We'd like to use non-normalized texcoords to index into a RECT
00273        * texture, but we can only use GL_REPEAT wrap mode with normalized
00274        * texcoords.  Darn.
00275        */
00276 
00277       /* MUL texTemp, INPUT[wincoord], 1/32; */
00278       newInst = tgsi_default_full_instruction();
00279       newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
00280       newInst.Instruction.NumDstRegs = 1;
00281       newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
00282       newInst.FullDstRegisters[0].DstRegister.Index = pctx->texTemp;
00283       newInst.Instruction.NumSrcRegs = 2;
00284       newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
00285       newInst.FullSrcRegisters[0].SrcRegister.Index = wincoordInput;
00286       newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_IMMEDIATE;
00287       newInst.FullSrcRegisters[1].SrcRegister.Index = pctx->numImmed;
00288       ctx->emit_instruction(ctx, &newInst);
00289 
00290       /* TEX texTemp, texTemp, sampler; */
00291       newInst = tgsi_default_full_instruction();
00292       newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
00293       newInst.Instruction.NumDstRegs = 1;
00294       newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
00295       newInst.FullDstRegisters[0].DstRegister.Index = pctx->texTemp;
00296       newInst.Instruction.NumSrcRegs = 2;
00297       newInst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
00298       newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
00299       newInst.FullSrcRegisters[0].SrcRegister.Index = pctx->texTemp;
00300       newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
00301       newInst.FullSrcRegisters[1].SrcRegister.Index = pctx->freeSampler;
00302       ctx->emit_instruction(ctx, &newInst);
00303 
00304       /* KIL -texTemp;   # if -texTemp < 0, KILL fragment */
00305       newInst = tgsi_default_full_instruction();
00306       newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
00307       newInst.Instruction.NumDstRegs = 0;
00308       newInst.Instruction.NumSrcRegs = 1;
00309       newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
00310       newInst.FullSrcRegisters[0].SrcRegister.Index = pctx->texTemp;
00311       newInst.FullSrcRegisters[0].SrcRegister.Negate = 1;
00312       ctx->emit_instruction(ctx, &newInst);
00313    }
00314 
00315    /* emit this instruction */
00316    ctx->emit_instruction(ctx, inst);
00317 }
00318 
00319 
00324 static boolean
00325 generate_pstip_fs(struct pstip_stage *pstip)
00326 {
00327    const struct pipe_shader_state *orig_fs = &pstip->fs->state;
00328    /*struct draw_context *draw = pstip->stage.draw;*/
00329    struct pipe_shader_state pstip_fs;
00330    struct pstip_transform_context transform;
00331 
00332 #define MAX 1000
00333 
00334    pstip_fs = *orig_fs; /* copy to init */
00335    pstip_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
00336    if (pstip_fs.tokens == NULL)
00337       return FALSE;
00338 
00339    memset(&transform, 0, sizeof(transform));
00340    transform.wincoordInput = -1;
00341    transform.maxInput = -1;
00342    transform.texTemp = -1;
00343    transform.firstInstruction = TRUE;
00344    transform.base.transform_instruction = pstip_transform_inst;
00345    transform.base.transform_declaration = pstip_transform_decl;
00346    transform.base.transform_immediate = pstip_transform_immed;
00347 
00348    tgsi_transform_shader(orig_fs->tokens,
00349                          (struct tgsi_token *) pstip_fs.tokens,
00350                          MAX, &transform.base);
00351 
00352 #if 0 /* DEBUG */
00353    tgsi_dump(orig_fs->tokens, 0);
00354    tgsi_dump(pstip_fs.tokens, 0);
00355 #endif
00356 
00357    pstip->fs->sampler_unit = transform.freeSampler;
00358    assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
00359 
00360    pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
00361 
00362    return TRUE;
00363 }
00364 
00365 
00369 static void
00370 pstip_update_texture(struct pstip_stage *pstip)
00371 {
00372    static const uint bit31 = 1 << 31;
00373    struct pipe_context *pipe = pstip->pipe;
00374    struct pipe_screen *screen = pipe->screen;
00375    struct pipe_surface *surface;
00376    const uint *stipple = pstip->state.stipple->stipple;
00377    uint i, j;
00378    ubyte *data;
00379 
00380    /* XXX: want to avoid flushing just because we use stipple: 
00381     */
00382    pipe->flush( pipe, PIPE_FLUSH_TEXTURE_CACHE, NULL );
00383 
00384    surface = screen->get_tex_surface(screen, pstip->texture, 0, 0, 0,
00385                                      PIPE_BUFFER_USAGE_CPU_WRITE);
00386    data = screen->surface_map(screen, surface,
00387                               PIPE_BUFFER_USAGE_CPU_WRITE);
00388 
00389    /*
00390     * Load alpha texture.
00391     * Note: 0 means keep the fragment, 255 means kill it.
00392     * We'll negate the texel value and use KILP which kills if value
00393     * is negative.
00394     */
00395    for (i = 0; i < 32; i++) {
00396       for (j = 0; j < 32; j++) {
00397          if (stipple[i] & (bit31 >> j)) {
00398             /* fragment "on" */
00399             data[i * surface->stride + j] = 0;
00400          }
00401          else {
00402             /* fragment "off" */
00403             data[i * surface->stride + j] = 255;
00404          }
00405       }
00406    }
00407 
00408    /* unmap */
00409    screen->surface_unmap(screen, surface);
00410    screen->tex_surface_release(screen, &surface);
00411 }
00412 
00413 
00417 static boolean
00418 pstip_create_texture(struct pstip_stage *pstip)
00419 {
00420    struct pipe_context *pipe = pstip->pipe;
00421    struct pipe_screen *screen = pipe->screen;
00422    struct pipe_texture texTemp;
00423 
00424    memset(&texTemp, 0, sizeof(texTemp));
00425    texTemp.target = PIPE_TEXTURE_2D;
00426    texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
00427    texTemp.last_level = 0;
00428    texTemp.width[0] = 32;
00429    texTemp.height[0] = 32;
00430    texTemp.depth[0] = 1;
00431    pf_get_block(texTemp.format, &texTemp.block);
00432 
00433    pstip->texture = screen->texture_create(screen, &texTemp);
00434    if (pstip->texture == NULL)
00435       return FALSE;
00436 
00437    return TRUE;
00438 }
00439 
00440 
00444 static boolean
00445 pstip_create_sampler(struct pstip_stage *pstip)
00446 {
00447    struct pipe_sampler_state sampler;
00448    struct pipe_context *pipe = pstip->pipe;
00449 
00450    memset(&sampler, 0, sizeof(sampler));
00451    sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
00452    sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
00453    sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
00454    sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
00455    sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
00456    sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
00457    sampler.normalized_coords = 1;
00458    sampler.min_lod = 0.0f;
00459    sampler.max_lod = 0.0f;
00460 
00461    pstip->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
00462    if (pstip->sampler_cso == NULL)
00463       return FALSE;
00464    
00465    return TRUE;
00466 }
00467 
00468 
00473 static boolean
00474 bind_pstip_fragment_shader(struct pstip_stage *pstip)
00475 {
00476    struct draw_context *draw = pstip->stage.draw;
00477    if (!pstip->fs->pstip_fs &&
00478        !generate_pstip_fs(pstip))
00479       return FALSE;
00480 
00481    draw->suspend_flushing = TRUE;
00482    pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
00483    draw->suspend_flushing = FALSE;
00484    return TRUE;
00485 }
00486 
00487 
00488 static INLINE struct pstip_stage *
00489 pstip_stage( struct draw_stage *stage )
00490 {
00491    return (struct pstip_stage *) stage;
00492 }
00493 
00494 
00495 static void
00496 pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
00497 {
00498    struct pstip_stage *pstip = pstip_stage(stage);
00499    struct pipe_context *pipe = pstip->pipe;
00500    struct draw_context *draw = stage->draw;
00501    uint num_samplers;
00502 
00503    assert(stage->draw->rasterizer->poly_stipple_enable);
00504 
00505    /* bind our fragprog */
00506    if (!bind_pstip_fragment_shader(pstip)) {
00507       stage->tri = draw_pipe_passthrough_tri;
00508       stage->tri(stage, header);
00509       return;
00510    }
00511       
00512 
00513    /* how many samplers? */
00514    /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
00515    num_samplers = MAX2(pstip->num_textures, pstip->num_samplers);
00516    num_samplers = MAX2(num_samplers, pstip->fs->sampler_unit + 1);
00517 
00518    /* plug in our sampler, texture */
00519    pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso;
00520    pipe_texture_reference(&pstip->state.textures[pstip->fs->sampler_unit],
00521                           pstip->texture);
00522 
00523    assert(num_samplers <= PIPE_MAX_SAMPLERS);
00524 
00525    draw->suspend_flushing = TRUE;
00526    pstip->driver_bind_sampler_states(pipe, num_samplers, pstip->state.samplers);
00527    pstip->driver_set_sampler_textures(pipe, num_samplers, pstip->state.textures);
00528    draw->suspend_flushing = FALSE;
00529 
00530    /* now really draw first triangle */
00531    stage->tri = draw_pipe_passthrough_tri;
00532    stage->tri(stage, header);
00533 }
00534 
00535 
00536 static void
00537 pstip_flush(struct draw_stage *stage, unsigned flags)
00538 {
00539    struct draw_context *draw = stage->draw;
00540    struct pstip_stage *pstip = pstip_stage(stage);
00541    struct pipe_context *pipe = pstip->pipe;
00542 
00543    stage->tri = pstip_first_tri;
00544    stage->next->flush( stage->next, flags );
00545 
00546    /* restore original frag shader, texture, sampler state */
00547    draw->suspend_flushing = TRUE;
00548    pstip->driver_bind_fs_state(pipe, pstip->fs->driver_fs);
00549    pstip->driver_bind_sampler_states(pipe, pstip->num_samplers,
00550                                      pstip->state.samplers);
00551    pstip->driver_set_sampler_textures(pipe, pstip->num_textures,
00552                                       pstip->state.textures);
00553    draw->suspend_flushing = FALSE;
00554 }
00555 
00556 
00557 static void
00558 pstip_reset_stipple_counter(struct draw_stage *stage)
00559 {
00560    stage->next->reset_stipple_counter( stage->next );
00561 }
00562 
00563 
00564 static void
00565 pstip_destroy(struct draw_stage *stage)
00566 {
00567    struct pstip_stage *pstip = pstip_stage(stage);
00568    uint i;
00569 
00570    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
00571       pipe_texture_reference(&pstip->state.textures[i], NULL);
00572    }
00573 
00574    pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso);
00575 
00576    pipe_texture_release(&pstip->texture);
00577 
00578    draw_free_temp_verts( stage );
00579    FREE( stage );
00580 }
00581 
00582 
00583 static struct pstip_stage *
00584 draw_pstip_stage(struct draw_context *draw)
00585 {
00586    struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
00587 
00588    draw_alloc_temp_verts( &pstip->stage, 8 );
00589 
00590    pstip->stage.draw = draw;
00591    pstip->stage.next = NULL;
00592    pstip->stage.point = draw_pipe_passthrough_point;
00593    pstip->stage.line = draw_pipe_passthrough_line;
00594    pstip->stage.tri = pstip_first_tri;
00595    pstip->stage.flush = pstip_flush;
00596    pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter;
00597    pstip->stage.destroy = pstip_destroy;
00598 
00599    return pstip;
00600 }
00601 
00602 
00603 static struct pstip_stage *
00604 pstip_stage_from_pipe(struct pipe_context *pipe)
00605 {
00606    struct draw_context *draw = (struct draw_context *) pipe->draw;
00607    return pstip_stage(draw->pipeline.pstipple);
00608 }
00609 
00610 
00615 static void *
00616 pstip_create_fs_state(struct pipe_context *pipe,
00617                        const struct pipe_shader_state *fs)
00618 {
00619    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
00620    struct pstip_fragment_shader *aafs = CALLOC_STRUCT(pstip_fragment_shader);
00621 
00622    if (aafs) {
00623       aafs->state = *fs;
00624 
00625       /* pass-through */
00626       aafs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
00627    }
00628 
00629    return aafs;
00630 }
00631 
00632 
00633 static void
00634 pstip_bind_fs_state(struct pipe_context *pipe, void *fs)
00635 {
00636    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
00637    struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs;
00638    /* save current */
00639    pstip->fs = aafs;
00640    /* pass-through */
00641    pstip->driver_bind_fs_state(pstip->pipe,
00642                                (aafs ? aafs->driver_fs : NULL));
00643 }
00644 
00645 
00646 static void
00647 pstip_delete_fs_state(struct pipe_context *pipe, void *fs)
00648 {
00649    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
00650    struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs;
00651    /* pass-through */
00652    pstip->driver_delete_fs_state(pstip->pipe, aafs->driver_fs);
00653    FREE(aafs);
00654 }
00655 
00656 
00657 static void
00658 pstip_bind_sampler_states(struct pipe_context *pipe,
00659                           unsigned num, void **sampler)
00660 {
00661    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
00662    uint i;
00663 
00664    /* save current */
00665    memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
00666    for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
00667       pstip->state.samplers[i] = NULL;
00668    }
00669 
00670    pstip->num_samplers = num;
00671    /* pass-through */
00672    pstip->driver_bind_sampler_states(pstip->pipe, num, sampler);
00673 }
00674 
00675 
00676 static void
00677 pstip_set_sampler_textures(struct pipe_context *pipe,
00678                            unsigned num, struct pipe_texture **texture)
00679 {
00680    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
00681    uint i;
00682 
00683    /* save current */
00684    for (i = 0; i < num; i++) {
00685       pipe_texture_reference(&pstip->state.textures[i], texture[i]);
00686    }
00687    for (; i < PIPE_MAX_SAMPLERS; i++) {
00688       pipe_texture_reference(&pstip->state.textures[i], NULL);
00689    }
00690 
00691    pstip->num_textures = num;
00692 
00693    /* pass-through */
00694    pstip->driver_set_sampler_textures(pstip->pipe, num, texture);
00695 }
00696 
00697 
00698 static void
00699 pstip_set_polygon_stipple(struct pipe_context *pipe,
00700                           const struct pipe_poly_stipple *stipple)
00701 {
00702    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
00703 
00704    /* save current */
00705    pstip->state.stipple = stipple;
00706 
00707    /* pass-through */
00708    pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
00709 
00710    pstip_update_texture(pstip);
00711 }
00712 
00713 
00719 boolean
00720 draw_install_pstipple_stage(struct draw_context *draw,
00721                             struct pipe_context *pipe)
00722 {
00723    struct pstip_stage *pstip;
00724 
00725    pipe->draw = (void *) draw;
00726 
00727    /*
00728     * Create / install pgon stipple drawing / prim stage
00729     */
00730    pstip = draw_pstip_stage( draw );
00731    if (pstip == NULL)
00732       goto fail;
00733 
00734    draw->pipeline.pstipple = &pstip->stage;
00735 
00736    pstip->pipe = pipe;
00737 
00738    /* create special texture, sampler state */
00739    if (!pstip_create_texture(pstip))
00740       goto fail;
00741 
00742    if (!pstip_create_sampler(pstip))
00743       goto fail;
00744 
00745    /* save original driver functions */
00746    pstip->driver_create_fs_state = pipe->create_fs_state;
00747    pstip->driver_bind_fs_state = pipe->bind_fs_state;
00748    pstip->driver_delete_fs_state = pipe->delete_fs_state;
00749 
00750    pstip->driver_bind_sampler_states = pipe->bind_sampler_states;
00751    pstip->driver_set_sampler_textures = pipe->set_sampler_textures;
00752    pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple;
00753 
00754    /* override the driver's functions */
00755    pipe->create_fs_state = pstip_create_fs_state;
00756    pipe->bind_fs_state = pstip_bind_fs_state;
00757    pipe->delete_fs_state = pstip_delete_fs_state;
00758 
00759    pipe->bind_sampler_states = pstip_bind_sampler_states;
00760    pipe->set_sampler_textures = pstip_set_sampler_textures;
00761    pipe->set_polygon_stipple = pstip_set_polygon_stipple;
00762 
00763    return TRUE;
00764 
00765  fail:
00766    if (pstip)
00767       pstip->stage.destroy( &pstip->stage );
00768 
00769    return FALSE;
00770 }

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