diff options
| author | Ben Skeggs <darktama@beleth.(none)> | 2008-02-22 12:25:15 +1100 | 
|---|---|---|
| committer | Ben Skeggs <darktama@beleth.(none)> | 2008-02-22 12:25:15 +1100 | 
| commit | f7922db610d05efee0ee8c5f0dadb69e3939482e (patch) | |
| tree | accfc0fdd96e1f572213cf69ea365c01bda0ef46 /src | |
| parent | 759fa5fcc8038af4845a6d9c57b75933ef26559c (diff) | |
| parent | 446bfc32a83008e0865ec869bc80b920c907f10f (diff) | |
Merge branch 'upstream-gallium-0.1' into nouveau-gallium-0.1
Conflicts:
	src/gallium/drivers/Makefile
Diffstat (limited to 'src')
162 files changed, 7126 insertions, 1981 deletions
diff --git a/src/SConscript b/src/SConscript new file mode 100644 index 0000000000..5b09943894 --- /dev/null +++ b/src/SConscript @@ -0,0 +1,7 @@ +Import('*') + +SConscript([ +	'gallium/SConscript', +	'mesa/SConscript', +	'gallium/winsys/SConscript', +]) diff --git a/src/gallium/Makefile b/src/gallium/Makefile index 89e068a449..568747e157 100644 --- a/src/gallium/Makefile +++ b/src/gallium/Makefile @@ -18,3 +18,4 @@ subdirs:  clean:  	rm -f `find . -name \*.[oa]` +	rm -f `find . -name depend` diff --git a/src/gallium/Makefile.template b/src/gallium/Makefile.template index 83b25f9b47..4e462b5c97 100644 --- a/src/gallium/Makefile.template +++ b/src/gallium/Makefile.template @@ -16,10 +16,8 @@ OBJECTS = $(C_SOURCES:.c=.o) \  INCLUDES = \  	-I. \  	-I$(TOP)/src/gallium/include \ -	-I$(TOP)/src/gallium/include/pipe \  	-I$(TOP)/src/gallium/auxiliary \  	-I$(TOP)/src/gallium/drivers \ -	-I$(TOP)/src/mesa \  	-I$(TOP)/include \          $(DRIVER_INCLUDES) diff --git a/src/gallium/SConscript b/src/gallium/SConscript index d9c20e0100..a08b4b830e 100644 --- a/src/gallium/SConscript +++ b/src/gallium/SConscript @@ -1,9 +1,29 @@  Import('*') -#env = env.Clone() +env = env.Clone() + +auxiliaries = [] + +Export('auxiliaries') + + +SConscript([ +	# NOTE: order matters! +	'auxiliary/util/SConscript', +	'auxiliary/rtasm/SConscript', +	'auxiliary/tgsi/SConscript', +	'auxiliary/cso_cache/SConscript', +	'auxiliary/draw/SConscript', +	'auxiliary/pipebuffer/SConscript', +]) + +if llvm: +	SConscript(['auxiliary/gallivm/SConscript'])  SConscript([ -	'softpipe/SConscript', -	'i915simple/SConscript', -	'i965simple/SConscript', +	'drivers/softpipe/SConscript', +	'drivers/i915simple/SConscript', +	'drivers/i965simple/SConscript', +	'drivers/failover/SConscript', +	#'drivers/cell/SConscript',  ]) diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index da68498aa1..eaa0f2fe4e 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -2,11 +2,7 @@ TOP = ../../..  include $(TOP)/configs/current -ifeq ($(CONFIG_NAME), linux-llvm) -LLVM_DIR = llvm -endif - -SUBDIRS = pipebuffer $(LLVM_DIR) +SUBDIRS = $(GALLIUM_AUXILIARY_DIRS)  default: subdirs diff --git a/src/gallium/auxiliary/cso_cache/Makefile b/src/gallium/auxiliary/cso_cache/Makefile new file mode 100644 index 0000000000..3e49266163 --- /dev/null +++ b/src/gallium/auxiliary/cso_cache/Makefile @@ -0,0 +1,13 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = cso_cache + +C_SOURCES = \ +	cso_cache.c \ +	cso_hash.c + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/auxiliary/cso_cache/SConscript b/src/gallium/auxiliary/cso_cache/SConscript new file mode 100644 index 0000000000..9751881613 --- /dev/null +++ b/src/gallium/auxiliary/cso_cache/SConscript @@ -0,0 +1,10 @@ +Import('*') + +cso_cache = env.ConvenienceLibrary( +	target = 'cso_cache', +	source = [ +		'cso_cache.c', +		'cso_hash.c', +	]) + +auxiliaries.insert(0, cso_cache) diff --git a/src/gallium/auxiliary/cso_cache/cso_hash.c b/src/gallium/auxiliary/cso_cache/cso_hash.c index 0338cb3b47..b40217c524 100644 --- a/src/gallium/auxiliary/cso_cache/cso_hash.c +++ b/src/gallium/auxiliary/cso_cache/cso_hash.c @@ -158,11 +158,14 @@ static void cso_data_rehash(struct cso_hash_data *hash, int hint)           while (firstNode != e) {              unsigned h = firstNode->key;              struct cso_node *lastNode = firstNode; +            struct cso_node *afterLastNode; +            struct cso_node **beforeFirstNode; +                          while (lastNode->next != e && lastNode->next->key == h)                 lastNode = lastNode->next; -            struct cso_node *afterLastNode = lastNode->next; -            struct cso_node **beforeFirstNode = &hash->buckets[h % hash->numBuckets]; +            afterLastNode = lastNode->next; +            beforeFirstNode = &hash->buckets[h % hash->numBuckets];              while (*beforeFirstNode != e)                 beforeFirstNode = &(*beforeFirstNode)->next;              lastNode->next = *beforeFirstNode; @@ -222,10 +225,12 @@ struct cso_hash_iter cso_hash_insert(struct cso_hash *hash,  {     cso_data_might_grow(hash->data.d); -   struct cso_node **nextNode = cso_hash_find_node(hash, key); -   struct cso_node *node = cso_hash_create_node(hash, key, data, nextNode); -   struct cso_hash_iter iter = {hash, node}; -   return iter; +   { +      struct cso_node **nextNode = cso_hash_find_node(hash, key); +      struct cso_node *node = cso_hash_create_node(hash, key, data, nextNode); +      struct cso_hash_iter iter = {hash, node}; +      return iter; +   }  }  struct cso_hash * cso_hash_create(void) @@ -290,6 +295,10 @@ static struct cso_node *cso_hash_data_next(struct cso_node *node)        struct cso_node *e;        struct cso_hash_data *d;     } a; +   int start; +   struct cso_node **bucket; +   int n; +     a.next = node->next;     if (!a.next) {        fprintf(stderr, "iterating beyond the last element\n"); @@ -298,9 +307,9 @@ static struct cso_node *cso_hash_data_next(struct cso_node *node)     if (a.next->next)        return a.next; -   int start = (node->key % a.d->numBuckets) + 1; -   struct cso_node **bucket = a.d->buckets + start; -   int n = a.d->numBuckets - start; +   start = (node->key % a.d->numBuckets) + 1; +   bucket = a.d->buckets + start; +   n = a.d->numBuckets - start;     while (n--) {        if (*bucket != a.e)           return *bucket; @@ -316,19 +325,21 @@ static struct cso_node *cso_hash_data_prev(struct cso_node *node)        struct cso_node *e;        struct cso_hash_data *d;     } a; +   int start; +   struct cso_node *sentinel; +   struct cso_node **bucket;     a.e = node;     while (a.e->next)        a.e = a.e->next; -   int start;     if (node == a.e)        start = a.d->numBuckets - 1;     else        start = node->key % a.d->numBuckets; -   struct cso_node *sentinel = node; -   struct cso_node **bucket = a.d->buckets + start; +   sentinel = node; +   bucket = a.d->buckets + start;     while (start >= 0) {        if (*bucket != sentinel) {           struct cso_node *prev = *bucket; diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile index fe9b150f30..c9980f0b83 100644 --- a/src/gallium/auxiliary/draw/Makefile +++ b/src/gallium/auxiliary/draw/Makefile @@ -1,2 +1,37 @@ -default: -	cd ../../../mesa ; make +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = draw + +C_SOURCES = \ +	draw_aaline.c \ +	draw_aapoint.c \ +	draw_clip.c \ +	draw_vs_exec.c \ +	draw_vs_sse.c \ +	draw_vs_llvm.c \ +	draw_context.c\ +	draw_cull.c \ +	draw_debug.c \ +	draw_flatshade.c \ +	draw_offset.c \ +	draw_prim.c \ +	draw_pstipple.c \ +	draw_stipple.c \ +	draw_twoside.c \ +	draw_unfilled.c \ +	draw_validate.c \ +	draw_vbuf.c \ +	draw_vertex.c \ +	draw_vertex_cache.c \ +	draw_vertex_fetch.c \ +	draw_vertex_shader.c \ +	draw_vf.c \ +	draw_vf_generic.c \ +	draw_vf_sse.c \ +	draw_wide_prims.c + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript new file mode 100644 index 0000000000..8e3a8caa74 --- /dev/null +++ b/src/gallium/auxiliary/draw/SConscript @@ -0,0 +1,31 @@ +Import('*') + +draw = env.ConvenienceLibrary( +	target = 'draw', +	source = [ +		'draw_clip.c', +		'draw_vs_exec.c', +		'draw_vs_sse.c', +		'draw_vs_llvm.c', +		'draw_context.c', +		'draw_cull.c', +		'draw_debug.c', +		'draw_flatshade.c', +		'draw_offset.c', +		'draw_prim.c', +		'draw_stipple.c', +		'draw_twoside.c', +		'draw_unfilled.c', +		'draw_validate.c', +		'draw_vbuf.c', +		'draw_vertex.c', +		'draw_vertex_cache.c', +		'draw_vertex_fetch.c', +		'draw_vertex_shader.c', +		'draw_vf.c', +		'draw_vf_generic.c', +		'draw_vf_sse.c', +		'draw_wide_prims.c', +	]) + +auxiliaries.insert(0, draw) diff --git a/src/gallium/auxiliary/draw/draw_aaline.c b/src/gallium/auxiliary/draw/draw_aaline.c new file mode 100644 index 0000000000..73a02a32e4 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_aaline.c @@ -0,0 +1,832 @@ +/************************************************************************** + *  + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *  + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *  + **************************************************************************/ + +/** + * AA line stage:  AA lines are converted to texture mapped triangles. + * + * Authors:  Brian Paul + */ + + +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_shader_tokens.h" + +#include "tgsi/util/tgsi_transform.h" +#include "tgsi/util/tgsi_dump.h" + +#include "draw_context.h" +#include "draw_private.h" + + +/** + * Max texture level for the alpha texture used for antialiasing + */ +#define MAX_TEXTURE_LEVEL  5   /* 32 x 32 */ + + +/** + * Subclass of pipe_shader_state to carry extra fragment shader info. + */ +struct aaline_fragment_shader +{ +   struct pipe_shader_state state; +   void *driver_fs; +   void *aaline_fs; +   void *aapoint_fs; /* not yet */ +   void *sprite_fs; /* not yet */ +}; + + +/** + * Subclass of draw_stage + */ +struct aaline_stage +{ +   struct draw_stage stage; + +   float half_line_width; + +   /** For AA lines, this is the vertex attrib slot for the new texcoords */ +   uint tex_slot; + +   void *sampler_cso; +   struct pipe_texture *texture; +   uint sampler_unit; + + +   /* +    * Currently bound state +    */ +   struct aaline_fragment_shader *fs; +   struct { +      void *sampler[PIPE_MAX_SAMPLERS]; +      struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; +   } state; + +   /* +    * Driver interface/override functions +    */ +   void * (*driver_create_fs_state)(struct pipe_context *, +                                    const struct pipe_shader_state *); +   void (*driver_bind_fs_state)(struct pipe_context *, void *); +   void (*driver_delete_fs_state)(struct pipe_context *, void *); + +   void (*driver_bind_sampler_state)(struct pipe_context *, unsigned, void *); + +   void (*driver_set_sampler_texture)(struct pipe_context *, +                                      unsigned sampler, +                                      struct pipe_texture *); + +   struct pipe_context *pipe; +}; + + + +/** + * Subclass of tgsi_transform_context, used for transforming the + * user's fragment shader to add the special AA instructions. + */ +struct aa_transform_context { +   struct tgsi_transform_context base; +   uint tempsUsed;  /**< bitmask */ +   int colorOutput; /**< which output is the primary color */ +   int maxSampler;  /**< max sampler index found */ +   int maxInput, maxGeneric;  /**< max input index found */ +   int colorTemp, texTemp;  /**< temp registers */ +   boolean firstInstruction; +}; + + +/** + * TGSI declaration transform callback. + * Look for a free sampler, a free input attrib, and two free temp regs. + */ +static void +aa_transform_decl(struct tgsi_transform_context *ctx, +                  struct tgsi_full_declaration *decl) +{ +   struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; + +   if (decl->Declaration.File == TGSI_FILE_OUTPUT && +       decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR && +       decl->Semantic.SemanticIndex == 0) { +      aactx->colorOutput = decl->u.DeclarationRange.First; +   } +   else if (decl->Declaration.File == TGSI_FILE_SAMPLER) { +      if ((int) decl->u.DeclarationRange.Last > aactx->maxSampler) +         aactx->maxSampler = decl->u.DeclarationRange.Last + 1; +   } +   else if (decl->Declaration.File == TGSI_FILE_INPUT) { +      if ((int) decl->u.DeclarationRange.Last > aactx->maxInput) +         aactx->maxInput = decl->u.DeclarationRange.Last; +      if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC && +           (int) decl->Semantic.SemanticIndex > aactx->maxGeneric) { +         aactx->maxGeneric = decl->Semantic.SemanticIndex; +      } +   } +   else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { +      uint i; +      for (i = decl->u.DeclarationRange.First; +           i <= decl->u.DeclarationRange.Last; i++) { +         aactx->tempsUsed |= (1 << i); +      } +   } + +   ctx->emit_declaration(ctx, decl); +} + + +/** + * TGSI instruction transform callback. + * Replace writes to result.color w/ a temp reg. + * Upon END instruction, insert texture sampling code for antialiasing. + */ +static void +aa_transform_inst(struct tgsi_transform_context *ctx, +                  struct tgsi_full_instruction *inst) +{ +   struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; + +   if (aactx->firstInstruction) { +      /* emit our new declarations before the first instruction */ + +      struct tgsi_full_declaration decl; +      uint i; + +      /* find two free temp regs */ +      for (i = 0; i < 32; i++) { +         if ((aactx->tempsUsed & (1 << i)) == 0) { +            /* found a free temp */ +            if (aactx->colorTemp < 0) +               aactx->colorTemp  = i; +            else if (aactx->texTemp < 0) +               aactx->texTemp  = i; +            else +               break; +         } +      } +      assert(aactx->colorTemp >= 0); +      assert(aactx->texTemp >= 0); + +      /* declare new generic input/texcoord */ +      decl = tgsi_default_full_declaration(); +      decl.Declaration.File = TGSI_FILE_INPUT; +      decl.Declaration.Semantic = 1; +      decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC; +      decl.Semantic.SemanticIndex = aactx->maxGeneric + 1; +      decl.Declaration.Interpolate = 1; +      /* XXX this could be linear... */ +      decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; +      decl.u.DeclarationRange.First =  +      decl.u.DeclarationRange.Last = aactx->maxInput + 1; +      ctx->emit_declaration(ctx, &decl); + +      /* declare new sampler */ +      decl = tgsi_default_full_declaration(); +      decl.Declaration.File = TGSI_FILE_SAMPLER; +      decl.u.DeclarationRange.First =  +      decl.u.DeclarationRange.Last = aactx->maxSampler + 1; +      ctx->emit_declaration(ctx, &decl); + +      /* declare new temp regs */ +      decl = tgsi_default_full_declaration(); +      decl.Declaration.File = TGSI_FILE_TEMPORARY; +      decl.u.DeclarationRange.First =  +      decl.u.DeclarationRange.Last = aactx->texTemp; +      ctx->emit_declaration(ctx, &decl); + +      decl = tgsi_default_full_declaration(); +      decl.Declaration.File = TGSI_FILE_TEMPORARY; +      decl.u.DeclarationRange.First =  +      decl.u.DeclarationRange.Last = aactx->colorTemp; +      ctx->emit_declaration(ctx, &decl); + +      aactx->firstInstruction = FALSE; +   } + +   if (inst->Instruction.Opcode == TGSI_OPCODE_END && +       aactx->colorOutput != -1) { +      struct tgsi_full_instruction newInst; + +      /* TEX */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_TEX; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullDstRegisters[0].DstRegister.Index = aactx->texTemp; +      newInst.Instruction.NumSrcRegs = 2; +      newInst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; +      newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->maxInput + 1; +      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; +      newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->maxSampler + 1; + +      ctx->emit_instruction(ctx, &newInst); + +      /* MOV rgb */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_MOV; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; +      newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XYZ; +      newInst.Instruction.NumSrcRegs = 1; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp; +      ctx->emit_instruction(ctx, &newInst); + +      /* MUL alpha */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_MUL; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; +      newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W; +      newInst.Instruction.NumSrcRegs = 2; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp; +      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->texTemp; +      ctx->emit_instruction(ctx, &newInst); + +      /* END */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_END; +      newInst.Instruction.NumDstRegs = 0; +      newInst.Instruction.NumSrcRegs = 0; +      ctx->emit_instruction(ctx, &newInst); +   } +   else { +      /* Not an END instruction. +       * Look for writes to result.color and replace with colorTemp reg. +       */ +      uint i; + +      for (i = 0; i < inst->Instruction.NumDstRegs; i++) { +         struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; +         if (dst->DstRegister.File == TGSI_FILE_OUTPUT && +             dst->DstRegister.Index == aactx->colorOutput) { +            dst->DstRegister.File = TGSI_FILE_TEMPORARY; +            dst->DstRegister.Index = aactx->colorTemp; +         } +      } + +      ctx->emit_instruction(ctx, inst); +   } +} + + +/** + * Generate the frag shader we'll use for drawing AA lines. + * This will be the user's shader plus some texture/modulate instructions. + */ +static void +generate_aaline_fs(struct aaline_stage *aaline) +{ +   const struct pipe_shader_state *orig_fs = &aaline->fs->state; +   struct draw_context *draw = aaline->stage.draw; +   struct pipe_shader_state aaline_fs; +   struct aa_transform_context transform; + +#define MAX 1000 + +   aaline_fs = *orig_fs; /* copy to init */ +   aaline_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX); + +   memset(&transform, 0, sizeof(transform)); +   transform.colorOutput = -1; +   transform.maxSampler = -1; +   transform.maxInput = -1; +   transform.maxGeneric = -1; +   transform.colorTemp = -1; +   transform.texTemp = -1; +   transform.firstInstruction = TRUE; +   transform.base.transform_instruction = aa_transform_inst; +   transform.base.transform_declaration = aa_transform_decl; + +   tgsi_transform_shader(orig_fs->tokens, +                         (struct tgsi_token *) aaline_fs.tokens, +                         MAX, &transform.base); + +#if 0 /* DEBUG */ +   tgsi_dump(orig_fs->tokens, 0); +   tgsi_dump(aaline_fs.tokens, 0); +#endif + +   aaline_fs.input_semantic_name[aaline_fs.num_inputs] = TGSI_SEMANTIC_GENERIC; +   aaline_fs.input_semantic_index[aaline_fs.num_inputs] = transform.maxGeneric + 1; +   aaline_fs.num_inputs++; + +   aaline->fs->aaline_fs +      = aaline->driver_create_fs_state(aaline->pipe, &aaline_fs); + +   /* advertise the extra post-transform vertex attributes which will have +    * the texcoords. +    */ +   draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; +   draw->extra_vp_outputs.semantic_index = transform.maxGeneric + 1; +} + + +/** + * Create the texture map we'll use for antialiasing the lines. + */ +static void +aaline_create_texture(struct aaline_stage *aaline) +{ +   struct pipe_context *pipe = aaline->pipe; +   struct pipe_texture texTemp; +   uint level; + +   memset(&texTemp, 0, sizeof(texTemp)); +   texTemp.target = PIPE_TEXTURE_2D; +   texTemp.format = PIPE_FORMAT_U_A8; /* XXX verify supported by driver! */ +   texTemp.last_level = MAX_TEXTURE_LEVEL; +   texTemp.width[0] = 1 << MAX_TEXTURE_LEVEL; +   texTemp.height[0] = 1 << MAX_TEXTURE_LEVEL; +   texTemp.depth[0] = 1; +   texTemp.cpp = 1; + +   aaline->texture = pipe->texture_create(pipe, &texTemp); + +   /* Fill in mipmap images. +    * Basically each level is solid opaque, except for the outermost +    * texels which are zero.  Special case the 1x1 and 2x2 levels. +    */ +   for (level = 0; level <= MAX_TEXTURE_LEVEL; level++) { +      struct pipe_surface *surface; +      const uint size = aaline->texture->width[level]; +      ubyte *data; +      uint i, j; + +      assert(aaline->texture->width[level] == aaline->texture->height[level]); + +      surface = pipe->get_tex_surface(pipe, aaline->texture, 0, level, 0); +      data = pipe_surface_map(surface); + +      for (i = 0; i < size; i++) { +         for (j = 0; j < size; j++) { +            ubyte d; +            if (size == 1) { +               d = 255; +            } +            else if (size == 2) { +               d = 200; /* tuneable */ +            } +            else if (i == 0 || j == 0 || i == size - 1 || j == size - 1) { +               d = 0; +            } +            else { +               d = 255; +            } +            data[i * surface->pitch + j] = d; +         } +      } + +      /* unmap */ +      pipe_surface_unmap(surface); +      pipe_surface_reference(&surface, NULL); +   } +} + + +/** + * Create the sampler CSO that'll be used for antialiasing. + * By using a mipmapped texture, we don't have to generate a different + * texture image for each line size. + */ +static void +aaline_create_sampler(struct aaline_stage *aaline) +{ +   struct pipe_sampler_state sampler; +   struct pipe_context *pipe = aaline->pipe; + +   memset(&sampler, 0, sizeof(sampler)); +   sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +   sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; +   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR; +   sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; +   sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; +   sampler.normalized_coords = 1; +   sampler.min_lod = 0.0f; +   sampler.max_lod = MAX_TEXTURE_LEVEL; + +   aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler); +} + + +/** + * When we're about to draw our first AA line in a batch, this function is + * called to tell the driver to bind our modified fragment shader. + */ +static void +bind_aaline_fragment_shader(struct aaline_stage *aaline) +{ +   if (!aaline->fs->aaline_fs) { +      generate_aaline_fs(aaline); +   } +   aaline->driver_bind_fs_state(aaline->pipe, aaline->fs->aaline_fs); +} + + + +static INLINE struct aaline_stage * +aaline_stage( struct draw_stage *stage ) +{ +   return (struct aaline_stage *) stage; +} + + +static void +passthrough_point(struct draw_stage *stage, struct prim_header *header) +{ +   stage->next->point(stage->next, header); +} + + +static void +passthrough_tri(struct draw_stage *stage, struct prim_header *header) +{ +   stage->next->tri(stage->next, header); +} + + +/** + * Draw a wide line by drawing a quad, using geometry which will + * fullfill GL's antialiased line requirements. + */ +static void +aaline_line(struct draw_stage *stage, struct prim_header *header) +{ +   const struct aaline_stage *aaline = aaline_stage(stage); +   const float half_width = aaline->half_line_width; +   struct prim_header tri; +   struct vertex_header *v[8]; +   uint texPos = aaline->tex_slot; +   float *pos, *tex; +   float dx = header->v[1]->data[0][0] - header->v[0]->data[0][0]; +   float dy = header->v[1]->data[0][1] - header->v[0]->data[0][1]; +   double a = atan2(dy, dx); +   float c_a = (float) cos(a), s_a = (float) sin(a); +   uint i; + +   /* XXX the ends of lines aren't quite perfect yet, but probably passable */ +   dx = 0.5F * half_width; +   dy = half_width; + +   /* allocate/dup new verts */ +   for (i = 0; i < 8; i++) { +      v[i] = dup_vert(stage, header->v[i/4], i); +   } + +   /* +    * Quad strip for line from v0 to v1 (*=endpoints): +    * +    *  1   3                     5   7 +    *  +---+---------------------+---+ +    *  |                             | +    *  | *v0                     v1* | +    *  |                             | +    *  +---+---------------------+---+ +    *  0   2                     4   6 +    */ + +   /* new verts */ +   pos = v[0]->data[0]; +   pos[0] += (-dx * c_a -  dy * s_a); +   pos[1] += (-dx * s_a +  dy * c_a); + +   pos = v[1]->data[0]; +   pos[0] += (-dx * c_a - -dy * s_a); +   pos[1] += (-dx * s_a + -dy * c_a); + +   pos = v[2]->data[0]; +   pos[0] += ( dx * c_a -  dy * s_a); +   pos[1] += ( dx * s_a +  dy * c_a); + +   pos = v[3]->data[0]; +   pos[0] += ( dx * c_a - -dy * s_a); +   pos[1] += ( dx * s_a + -dy * c_a); + +   pos = v[4]->data[0]; +   pos[0] += (-dx * c_a -  dy * s_a); +   pos[1] += (-dx * s_a +  dy * c_a); + +   pos = v[5]->data[0]; +   pos[0] += (-dx * c_a - -dy * s_a); +   pos[1] += (-dx * s_a + -dy * c_a); + +   pos = v[6]->data[0]; +   pos[0] += ( dx * c_a -  dy * s_a); +   pos[1] += ( dx * s_a +  dy * c_a); + +   pos = v[7]->data[0]; +   pos[0] += ( dx * c_a - -dy * s_a); +   pos[1] += ( dx * s_a + -dy * c_a); + +   /* new texcoords */ +   tex = v[0]->data[texPos]; +   ASSIGN_4V(tex, 0, 0, 0, 1); + +   tex = v[1]->data[texPos]; +   ASSIGN_4V(tex, 0, 1, 0, 1); + +   tex = v[2]->data[texPos]; +   ASSIGN_4V(tex, .5, 0, 0, 1); + +   tex = v[3]->data[texPos]; +   ASSIGN_4V(tex, .5, 1, 0, 1); + +   tex = v[4]->data[texPos]; +   ASSIGN_4V(tex, .5, 0, 0, 1); + +   tex = v[5]->data[texPos]; +   ASSIGN_4V(tex, .5, 1, 0, 1); + +   tex = v[6]->data[texPos]; +   ASSIGN_4V(tex, 1, 0, 0, 1); + +   tex = v[7]->data[texPos]; +   ASSIGN_4V(tex, 1, 1, 0, 1); + +   /* emit 6 tris for the quad strip */ +   tri.v[0] = v[2];  tri.v[1] = v[1];  tri.v[2] = v[0]; +   stage->next->tri( stage->next, &tri ); + +   tri.v[0] = v[3];  tri.v[1] = v[1];  tri.v[2] = v[2]; +   stage->next->tri( stage->next, &tri ); + +   tri.v[0] = v[4];  tri.v[1] = v[3];  tri.v[2] = v[2]; +   stage->next->tri( stage->next, &tri ); + +   tri.v[0] = v[5];  tri.v[1] = v[3];  tri.v[2] = v[4]; +   stage->next->tri( stage->next, &tri ); + +   tri.v[0] = v[6];  tri.v[1] = v[5];  tri.v[2] = v[4]; +   stage->next->tri( stage->next, &tri ); + +   tri.v[0] = v[7];  tri.v[1] = v[5];  tri.v[2] = v[6]; +   stage->next->tri( stage->next, &tri ); +} + + +static void +aaline_first_line(struct draw_stage *stage, struct prim_header *header) +{ +   auto struct aaline_stage *aaline = aaline_stage(stage); +   struct draw_context *draw = stage->draw; +   struct pipe_context *pipe = aaline->pipe; + +   assert(draw->rasterizer->line_smooth); + +   if (draw->rasterizer->line_width <= 3.0) +      aaline->half_line_width = 1.5f; +   else +      aaline->half_line_width = 0.5f * draw->rasterizer->line_width; + +   aaline->tex_slot = draw->num_vs_outputs; +   assert(aaline->tex_slot > 0); /* output[0] is vertex pos */ +   draw->extra_vp_outputs.slot = aaline->tex_slot; + +   /* +    * Bind our fragprog, sampler and texture +    */ +   bind_aaline_fragment_shader(aaline); + +   aaline->driver_bind_sampler_state(pipe, aaline->sampler_unit, aaline->sampler_cso); +   aaline->driver_set_sampler_texture(pipe, aaline->sampler_unit, aaline->texture); + +   /* now really draw first line */ +   stage->line = aaline_line; +   stage->line(stage, header); +} + + +static void +aaline_flush(struct draw_stage *stage, unsigned flags) +{ +   struct draw_context *draw = stage->draw; +   struct aaline_stage *aaline = aaline_stage(stage); +   struct pipe_context *pipe = aaline->pipe; + +   stage->line = aaline_first_line; +   stage->next->flush( stage->next, flags ); + +   /* restore original frag shader */ +   aaline->driver_bind_fs_state(pipe, aaline->fs->driver_fs); + +   /* XXX restore original texture, sampler state */ +   aaline->driver_bind_sampler_state(pipe, aaline->sampler_unit, +                                 aaline->state.sampler[aaline->sampler_unit]); +   aaline->driver_set_sampler_texture(pipe, aaline->sampler_unit, +                                 aaline->state.texture[aaline->sampler_unit]); + +   draw->extra_vp_outputs.slot = 0; +} + + +static void +aaline_reset_stipple_counter(struct draw_stage *stage) +{ +   stage->next->reset_stipple_counter( stage->next ); +} + + +static void +aaline_destroy(struct draw_stage *stage) +{ +   draw_free_temp_verts( stage ); +   FREE( stage ); +} + + +static struct aaline_stage * +draw_aaline_stage(struct draw_context *draw) +{ +   struct aaline_stage *aaline = CALLOC_STRUCT(aaline_stage); + +   draw_alloc_temp_verts( &aaline->stage, 8 ); + +   aaline->stage.draw = draw; +   aaline->stage.next = NULL; +   aaline->stage.point = passthrough_point; +   aaline->stage.line = aaline_first_line; +   aaline->stage.tri = passthrough_tri; +   aaline->stage.flush = aaline_flush; +   aaline->stage.reset_stipple_counter = aaline_reset_stipple_counter; +   aaline->stage.destroy = aaline_destroy; + +   return aaline; +} + + +/* + * XXX temporary? solution to mapping a pipe_context to a aaline_stage. + */ + +#define MAX_CONTEXTS 10 + +static struct pipe_context *Pipe[MAX_CONTEXTS]; +static struct aaline_stage *Stage[MAX_CONTEXTS]; +static uint NumContexts; + +static void +add_aa_pipe_context(struct pipe_context *pipe, struct aaline_stage *aa) +{ +   assert(NumContexts < MAX_CONTEXTS); +   Pipe[NumContexts] = pipe; +   Stage[NumContexts] = aa; +   NumContexts++; +} + +static struct aaline_stage * +aaline_stage_from_pipe(struct pipe_context *pipe) +{ +   uint i; +   for (i = 0; i < NumContexts; i++) { +      if (Pipe[i] == pipe) +         return Stage[i]; +   } +   assert(0); +   return NULL; +} + + +/** + * This function overrides the driver's create_fs_state() function and + * will typically be called by the state tracker. + */ +static void * +aaline_create_fs_state(struct pipe_context *pipe, +                       const struct pipe_shader_state *fs) +{ +   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); +   struct aaline_fragment_shader *aafs = CALLOC_STRUCT(aaline_fragment_shader); + +   if (aafs) { +      aafs->state = *fs; + +      /* pass-through */ +      aafs->driver_fs = aaline->driver_create_fs_state(aaline->pipe, fs); +   } + +   return aafs; +} + + +static void +aaline_bind_fs_state(struct pipe_context *pipe, void *fs) +{ +   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); +   struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs; +   /* save current */ +   aaline->fs = aafs; +   /* pass-through */ +   aaline->driver_bind_fs_state(aaline->pipe, aafs->driver_fs); +} + + +static void +aaline_delete_fs_state(struct pipe_context *pipe, void *fs) +{ +   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); +   struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs; +   /* pass-through */ +   aaline->driver_delete_fs_state(aaline->pipe, aafs->driver_fs); +   FREE(aafs); +} + + +static void +aaline_bind_sampler_state(struct pipe_context *pipe, +                          unsigned unit, void *sampler) +{ +   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); +   /* save current */ +   aaline->state.sampler[unit] = sampler; +   /* pass-through */ +   aaline->driver_bind_sampler_state(aaline->pipe, unit, sampler); +} + + +static void +aaline_set_sampler_texture(struct pipe_context *pipe, +                           unsigned sampler, struct pipe_texture *texture) +{ +   struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); +   /* save current */ +   aaline->state.texture[sampler] = texture; +   /* pass-through */ +   aaline->driver_set_sampler_texture(aaline->pipe, sampler, texture); +} + + +/** + * Called by drivers that want to install this AA line prim stage + * into the draw module's pipeline.  This will not be used if the + * hardware has native support for AA lines. + */ +void +draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe) +{ +   struct aaline_stage *aaline; + +   /* +    * Create / install AA line drawing / prim stage +    */ +   aaline = draw_aaline_stage( draw ); +   assert(aaline); +   draw->pipeline.aaline = &aaline->stage; + +   aaline->pipe = pipe; + +   /* create special texture, sampler state */ +   aaline_create_texture(aaline); +   aaline_create_sampler(aaline); + +   /* save original driver functions */ +   aaline->driver_create_fs_state = pipe->create_fs_state; +   aaline->driver_bind_fs_state = pipe->bind_fs_state; +   aaline->driver_delete_fs_state = pipe->delete_fs_state; + +   aaline->driver_bind_sampler_state = pipe->bind_sampler_state; +   aaline->driver_set_sampler_texture = pipe->set_sampler_texture; + +   /* override the driver's functions */ +   pipe->create_fs_state = aaline_create_fs_state; +   pipe->bind_fs_state = aaline_bind_fs_state; +   pipe->delete_fs_state = aaline_delete_fs_state; + +   pipe->bind_sampler_state = aaline_bind_sampler_state; +   pipe->set_sampler_texture = aaline_set_sampler_texture; + +   add_aa_pipe_context(pipe, aaline); +} diff --git a/src/gallium/auxiliary/draw/draw_aapoint.c b/src/gallium/auxiliary/draw/draw_aapoint.c new file mode 100644 index 0000000000..43119cc70b --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_aapoint.c @@ -0,0 +1,875 @@ +/************************************************************************** + *  + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *  + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *  + **************************************************************************/ + +/** + * 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 + */ + + +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_shader_tokens.h" + +#include "tgsi/util/tgsi_transform.h" +#include "tgsi/util/tgsi_dump.h" + +#include "draw_context.h" +#include "draw_private.h" + + +/* + * Enabling NORMALIZE might give _slightly_ better results. + * Basically, it controls whether we compute distance as d=sqrt(x*x+y*y) or + * d=x*x+y*y.  Since we're working with a unit circle, the later seems + * close enough and saves some costly instructions. + */ +#define NORMALIZE 0 + + +/** + * Subclass of pipe_shader_state to carry extra fragment shader info. + */ +struct aapoint_fragment_shader +{ +   struct pipe_shader_state state; +   void *driver_fs;   /**< the regular shader */ +   void *aapoint_fs;  /**< the aa point-augmented shader */ +}; + + +/** + * Subclass of draw_stage + */ +struct aapoint_stage +{ +   struct draw_stage stage; + +   int psize_slot; +   float radius; + +   /** this is the vertex attrib slot for the new texcoords */ +   uint tex_slot; + +   /* +    * Currently bound state +    */ +   struct aapoint_fragment_shader *fs; + +   /* +    * Driver interface/override functions +    */ +   void * (*driver_create_fs_state)(struct pipe_context *, +                                    const struct pipe_shader_state *); +   void (*driver_bind_fs_state)(struct pipe_context *, void *); +   void (*driver_delete_fs_state)(struct pipe_context *, void *); + +   struct pipe_context *pipe; +}; + + + +/** + * Subclass of tgsi_transform_context, used for transforming the + * user's fragment shader to add the special AA instructions. + */ +struct aa_transform_context { +   struct tgsi_transform_context base; +   uint tempsUsed;  /**< bitmask */ +   int colorOutput; /**< which output is the primary color */ +   int maxInput, maxGeneric;  /**< max input index found */ +   int tmp0, colorTemp;  /**< temp registers */ +   boolean firstInstruction; +}; + + +/** + * TGSI declaration transform callback. + * Look for two free temp regs and available input reg for new texcoords. + */ +static void +aa_transform_decl(struct tgsi_transform_context *ctx, +                  struct tgsi_full_declaration *decl) +{ +   struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; + +   if (decl->Declaration.File == TGSI_FILE_OUTPUT && +       decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR && +       decl->Semantic.SemanticIndex == 0) { +      aactx->colorOutput = decl->u.DeclarationRange.First; +   } +   else if (decl->Declaration.File == TGSI_FILE_INPUT) { +      if ((int) decl->u.DeclarationRange.Last > aactx->maxInput) +         aactx->maxInput = decl->u.DeclarationRange.Last; +      if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC && +           (int) decl->Semantic.SemanticIndex > aactx->maxGeneric) { +         aactx->maxGeneric = decl->Semantic.SemanticIndex; +      } +   } +   else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { +      uint i; +      for (i = decl->u.DeclarationRange.First; +           i <= decl->u.DeclarationRange.Last; i++) { +         aactx->tempsUsed |= (1 << i); +      } +   } + +   ctx->emit_declaration(ctx, decl); +} + + +/** + * TGSI instruction transform callback. + * Replace writes to result.color w/ a temp reg. + * Upon END instruction, insert texture sampling code for antialiasing. + */ +static void +aa_transform_inst(struct tgsi_transform_context *ctx, +                  struct tgsi_full_instruction *inst) +{ +   struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; +   struct tgsi_full_instruction newInst; + +   if (aactx->firstInstruction) { +      /* emit our new declarations before the first instruction */ + +      struct tgsi_full_declaration decl; +      const int texInput = aactx->maxInput + 1; +      int tmp0; +      uint i; + +      /* find two free temp regs */ +      for (i = 0; i < 32; i++) { +         if ((aactx->tempsUsed & (1 << i)) == 0) { +            /* found a free temp */ +            if (aactx->tmp0 < 0) +               aactx->tmp0 = i; +            else if (aactx->colorTemp < 0) +               aactx->colorTemp = i; +            else +               break; +         } +      } + +      assert(aactx->colorTemp != aactx->tmp0); + +      tmp0 = aactx->tmp0; + +      /* declare new generic input/texcoord */ +      decl = tgsi_default_full_declaration(); +      decl.Declaration.File = TGSI_FILE_INPUT; +      decl.Declaration.Semantic = 1; +      decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC; +      decl.Semantic.SemanticIndex = aactx->maxGeneric + 1; +      decl.Declaration.Interpolate = 1; +      /* XXX this could be linear... */ +      decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; +      decl.u.DeclarationRange.First =  +      decl.u.DeclarationRange.Last = texInput; +      ctx->emit_declaration(ctx, &decl); + +      /* declare new temp regs */ +      decl = tgsi_default_full_declaration(); +      decl.Declaration.File = TGSI_FILE_TEMPORARY; +      decl.u.DeclarationRange.First =  +      decl.u.DeclarationRange.Last = tmp0; +      ctx->emit_declaration(ctx, &decl); + +      decl = tgsi_default_full_declaration(); +      decl.Declaration.File = TGSI_FILE_TEMPORARY; +      decl.u.DeclarationRange.First =  +      decl.u.DeclarationRange.Last = aactx->colorTemp; +      ctx->emit_declaration(ctx, &decl); + +      aactx->firstInstruction = FALSE; + + +      /* +       * Emit code to compute fragment coverage, kill if outside point radius +       * +       * Temp reg0 usage: +       *  t0.x = distance of fragment from center point +       *  t0.y = boolean, is t0.x > 1 ? +       *  t0.z = temporary for computing 1/(1-k) value +       *  t0.w = final coverage value +       */ + +      /* MUL t0.xy, tex, tex;  # compute x^2, y^2 */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_MUL; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XY; +      newInst.Instruction.NumSrcRegs = 2; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; +      newInst.FullSrcRegisters[0].SrcRegister.Index = texInput; +      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT; +      newInst.FullSrcRegisters[1].SrcRegister.Index = texInput; +      ctx->emit_instruction(ctx, &newInst); + +      /* ADD t0.x, t0.x, t0.y;  # x^2 + y^2 */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_ADD; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X; +      newInst.Instruction.NumSrcRegs = 2; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0; +      newInst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; +      ctx->emit_instruction(ctx, &newInst); + +#if NORMALIZE  /* OPTIONAL normalization of length */ +      /* RSQ t0.x, t0.x; */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_RSQ; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X; +      newInst.Instruction.NumSrcRegs = 1; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; +      ctx->emit_instruction(ctx, &newInst); + +      /* RCP t0.x, t0.x; */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_RCP; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X; +      newInst.Instruction.NumSrcRegs = 1; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; +      ctx->emit_instruction(ctx, &newInst); +#endif + +      /* SGT t0.y, t0.xxxx, t0.wwww;  # bool b = d > 1 (NOTE t0.w == 1) */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_SGT; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y; +      newInst.Instruction.NumSrcRegs = 2; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT; +      newInst.FullSrcRegisters[1].SrcRegister.Index = texInput; +      newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_W; +      ctx->emit_instruction(ctx, &newInst); + +      /* KILP -t0.yyyy;   # if b, KILL */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_KILP; +      newInst.Instruction.NumDstRegs = 0; +      newInst.Instruction.NumSrcRegs = 1; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; +      newInst.FullSrcRegisters[0].SrcRegister.Negate = 1; +      ctx->emit_instruction(ctx, &newInst); + +      /* SGT t0.y, t0.x, tex.z;  # bool b = distance > k */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_SGT; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y; +      newInst.Instruction.NumSrcRegs = 2; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; +      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT; +      newInst.FullSrcRegisters[1].SrcRegister.Index = texInput; +      newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Z; +      ctx->emit_instruction(ctx, &newInst); + +      /* IF t0.y   # if b then */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_IF; +      newInst.Instruction.NumDstRegs = 0; +      newInst.Instruction.NumSrcRegs = 1; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; +      newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; +      ctx->emit_instruction(ctx, &newInst); + +      { +         /* compute coverage factor = (1-d)/(1-k) */ + +         /* SUB t0.z, tex.w, tex.z;  # m = 1 - k */ +         newInst = tgsi_default_full_instruction(); +         newInst.Instruction.Opcode = TGSI_OPCODE_SUB; +         newInst.Instruction.NumDstRegs = 1; +         newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +         newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +         newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Z; +         newInst.Instruction.NumSrcRegs = 2; +         newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; +         newInst.FullSrcRegisters[0].SrcRegister.Index = texInput; +         newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W; +         newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT; +         newInst.FullSrcRegisters[1].SrcRegister.Index = texInput; +         newInst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z; +         ctx->emit_instruction(ctx, &newInst); + +         /* RCP t0.z, t0.z;  # t0.z = 1 / m */ +         newInst = tgsi_default_full_instruction(); +         newInst.Instruction.Opcode = TGSI_OPCODE_RCP; +         newInst.Instruction.NumDstRegs = 1; +         newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +         newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +         newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Z; +         newInst.Instruction.NumSrcRegs = 1; +         newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +         newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; +         newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Z; +         ctx->emit_instruction(ctx, &newInst); + +         /* SUB t0.x, 1, t0.x;  # d = 1 - d */ +         newInst = tgsi_default_full_instruction(); +         newInst.Instruction.Opcode = TGSI_OPCODE_SUB; +         newInst.Instruction.NumDstRegs = 1; +         newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +         newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +         newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X; +         newInst.Instruction.NumSrcRegs = 2; +         newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; +         newInst.FullSrcRegisters[0].SrcRegister.Index = texInput; +         newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_W; +         newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY; +         newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0; +         newInst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; +         ctx->emit_instruction(ctx, &newInst); + +         /* MUL t0.w, t0.x, t0.z;   # coverage = d * m */ +         newInst = tgsi_default_full_instruction(); +         newInst.Instruction.Opcode = TGSI_OPCODE_MUL; +         newInst.Instruction.NumDstRegs = 1; +         newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +         newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +         newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W; +         newInst.Instruction.NumSrcRegs = 2; +         newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +         newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0; +         newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; +         newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY; +         newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0; +         newInst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Z; +         ctx->emit_instruction(ctx, &newInst); +      } + +      /* ELSE */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_ELSE; +      newInst.Instruction.NumDstRegs = 0; +      newInst.Instruction.NumSrcRegs = 0; +      ctx->emit_instruction(ctx, &newInst); + +      { +         /* MOV t0.w, tex.w;  # coverage = 1.0 */ +         newInst = tgsi_default_full_instruction(); +         newInst.Instruction.Opcode = TGSI_OPCODE_MOV; +         newInst.Instruction.NumDstRegs = 1; +         newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +         newInst.FullDstRegisters[0].DstRegister.Index = tmp0; +         newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W; +         newInst.Instruction.NumSrcRegs = 1; +         newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; +         newInst.FullSrcRegisters[0].SrcRegister.Index = texInput; +         ctx->emit_instruction(ctx, &newInst); +      } + +      /* ENDIF */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_ENDIF; +      newInst.Instruction.NumDstRegs = 0; +      newInst.Instruction.NumSrcRegs = 0; +      ctx->emit_instruction(ctx, &newInst); +   } + +   if (inst->Instruction.Opcode == TGSI_OPCODE_END) { +      /* add alpha modulation code at tail of program */ + +      /* MOV result.color.xyz, colorTemp; */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_MOV; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; +      newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XYZ; +      newInst.Instruction.NumSrcRegs = 1; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp; +      ctx->emit_instruction(ctx, &newInst); + +      /* MUL result.color.w, colorTemp, tmp0.w; */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_MUL; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; +      newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput; +      newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W; +      newInst.Instruction.NumSrcRegs = 2; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp; +      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->tmp0; +      ctx->emit_instruction(ctx, &newInst); +   } +   else { +      /* Not an END instruction. +       * Look for writes to result.color and replace with colorTemp reg. +       */ +      uint i; + +      for (i = 0; i < inst->Instruction.NumDstRegs; i++) { +         struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; +         if (dst->DstRegister.File == TGSI_FILE_OUTPUT && +             dst->DstRegister.Index == aactx->colorOutput) { +            dst->DstRegister.File = TGSI_FILE_TEMPORARY; +            dst->DstRegister.Index = aactx->colorTemp; +         } +      } +   } + +   ctx->emit_instruction(ctx, inst); +} + + +/** + * Generate the frag shader we'll use for drawing AA lines. + * This will be the user's shader plus some texture/modulate instructions. + */ +static void +generate_aapoint_fs(struct aapoint_stage *aapoint) +{ +   const struct pipe_shader_state *orig_fs = &aapoint->fs->state; +   struct draw_context *draw = aapoint->stage.draw; +   struct pipe_shader_state aapoint_fs; +   struct aa_transform_context transform; + +#define MAX 1000 + +   aapoint_fs = *orig_fs; /* copy to init */ +   aapoint_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX); + +   memset(&transform, 0, sizeof(transform)); +   transform.colorOutput = -1; +   transform.maxInput = -1; +   transform.maxGeneric = -1; +   transform.colorTemp = -1; +   transform.tmp0 = -1; +   transform.firstInstruction = TRUE; +   transform.base.transform_instruction = aa_transform_inst; +   transform.base.transform_declaration = aa_transform_decl; + +   tgsi_transform_shader(orig_fs->tokens, +                         (struct tgsi_token *) aapoint_fs.tokens, +                         MAX, &transform.base); + +#if 0 /* DEBUG */ +   tgsi_dump(orig_fs->tokens, 0); +   tgsi_dump(aapoint_fs.tokens, 0); +#endif + +   aapoint_fs.input_semantic_name[aapoint_fs.num_inputs] = TGSI_SEMANTIC_GENERIC; +   aapoint_fs.input_semantic_index[aapoint_fs.num_inputs] = transform.maxGeneric + 1; +   aapoint_fs.num_inputs++; + +   aapoint->fs->aapoint_fs +      = aapoint->driver_create_fs_state(aapoint->pipe, &aapoint_fs); + +   /* advertise the extra post-transform vertex attributes which will have +    * the texcoords. +    */ +   draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; +   draw->extra_vp_outputs.semantic_index = transform.maxGeneric + 1; +} + + +/** + * When we're about to draw our first AA line in a batch, this function is + * called to tell the driver to bind our modified fragment shader. + */ +static void +bind_aapoint_fragment_shader(struct aapoint_stage *aapoint) +{ +   if (!aapoint->fs->aapoint_fs) { +      generate_aapoint_fs(aapoint); +   } +   aapoint->driver_bind_fs_state(aapoint->pipe, aapoint->fs->aapoint_fs); +} + + + +static INLINE struct aapoint_stage * +aapoint_stage( struct draw_stage *stage ) +{ +   return (struct aapoint_stage *) stage; +} + + +static void +passthrough_line(struct draw_stage *stage, struct prim_header *header) +{ +   stage->next->line(stage->next, header); +} + + +static void +passthrough_tri(struct draw_stage *stage, struct prim_header *header) +{ +   stage->next->tri(stage->next, header); +} + + +/** + * Draw an AA point by drawing a quad. + */ +static void +aapoint_point(struct draw_stage *stage, struct prim_header *header) +{ +   const struct aapoint_stage *aapoint = aapoint_stage(stage); +   struct prim_header tri; +   struct vertex_header *v[4]; +   uint texPos = aapoint->tex_slot; +   float radius, *pos, *tex; +   uint i; +   float k; + +   if (aapoint->psize_slot >= 0) { +      radius = 0.5f * header->v[0]->data[aapoint->psize_slot][0]; +   } +   else { +      radius = aapoint->radius; +   } + +   /* +    * Note: the texcoords (generic attrib, really) we use are special: +    * The S and T components simply vary from -1 to +1. +    * The R component is k, below. +    * The Q component is 1.0 and will used as a handy constant in the +    * fragment shader. +    */ + +   /* +    * k is the threshold distance from the point's center at which +    * we begin alpha attenuation (the coverage value). +    * Operating within a unit circle, we'll compute the fragment's +    * distance 'd' from the center point using the texcoords. +    * IF d > 1.0 THEN +    *    KILL fragment +    * ELSE IF d > k THEN +    *    compute coverage in [0,1] proportional to d in [k, 1]. +    * ELSE +    *    coverage = 1.0;  // full coverage +    * ENDIF +    */ + +#if !NORMALIZE +   k = 1.0 / radius; +   k = 1.0 - 2.0 * k + k * k; +#else +   k = 1.0 - 1.0 / radius; +#endif + +   /* allocate/dup new verts */ +   for (i = 0; i < 4; i++) { +      v[i] = dup_vert(stage, header->v[0], i); +   } + +   /* new verts */ +   pos = v[0]->data[0]; +   pos[0] -= radius; +   pos[1] -= radius; + +   pos = v[1]->data[0]; +   pos[0] += radius; +   pos[1] -= radius; + +   pos = v[2]->data[0]; +   pos[0] += radius; +   pos[1] += radius; + +   pos = v[3]->data[0]; +   pos[0] -= radius; +   pos[1] += radius; + +   /* new texcoords */ +   tex = v[0]->data[texPos]; +   ASSIGN_4V(tex, -1, -1, k, 1); + +   tex = v[1]->data[texPos]; +   ASSIGN_4V(tex,  1, -1, k, 1); + +   tex = v[2]->data[texPos]; +   ASSIGN_4V(tex,  1,  1, k, 1); + +   tex = v[3]->data[texPos]; +   ASSIGN_4V(tex, -1,  1, k, 1); + +   /* emit 2 tris for the quad strip */ +   tri.v[0] = v[0]; +   tri.v[1] = v[1]; +   tri.v[2] = v[2]; +   stage->next->tri( stage->next, &tri ); + +   tri.v[0] = v[0]; +   tri.v[1] = v[2]; +   tri.v[2] = v[3]; +   stage->next->tri( stage->next, &tri ); +} + + +static void +aapoint_first_point(struct draw_stage *stage, struct prim_header *header) +{ +   auto struct aapoint_stage *aapoint = aapoint_stage(stage); +   struct draw_context *draw = stage->draw; + +   assert(draw->rasterizer->point_smooth); + +   if (draw->rasterizer->point_size <= 2.0) +      aapoint->radius = 1.0; +   else +      aapoint->radius = 0.5f * draw->rasterizer->point_size; + +   aapoint->tex_slot = draw->num_vs_outputs; +   assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */ +   draw->extra_vp_outputs.slot = aapoint->tex_slot; + +   /* +    * Bind our fragprog. +    */ +   bind_aapoint_fragment_shader(aapoint); + +   /* find psize slot in post-transform vertex */ +   aapoint->psize_slot = -1; +   if (draw->rasterizer->point_size_per_vertex) { +      /* find PSIZ vertex output */ +      const struct draw_vertex_shader *vs = draw->vertex_shader; +      uint i; +      for (i = 0; i < vs->state->num_outputs; i++) { +         if (vs->state->output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) { +            aapoint->psize_slot = i; +            break; +         } +      } +   } + +   /* now really draw first line */ +   stage->point = aapoint_point; +   stage->point(stage, header); +} + + +static void +aapoint_flush(struct draw_stage *stage, unsigned flags) +{ +   struct draw_context *draw = stage->draw; +   struct aapoint_stage *aapoint = aapoint_stage(stage); +   struct pipe_context *pipe = aapoint->pipe; + +   stage->point = aapoint_first_point; +   stage->next->flush( stage->next, flags ); + +   /* restore original frag shader */ +   aapoint->driver_bind_fs_state(pipe, aapoint->fs->driver_fs); + +   draw->extra_vp_outputs.slot = 0; +} + + +static void +aapoint_reset_stipple_counter(struct draw_stage *stage) +{ +   stage->next->reset_stipple_counter( stage->next ); +} + + +static void +aapoint_destroy(struct draw_stage *stage) +{ +   draw_free_temp_verts( stage ); +   FREE( stage ); +} + + +static struct aapoint_stage * +draw_aapoint_stage(struct draw_context *draw) +{ +   struct aapoint_stage *aapoint = CALLOC_STRUCT(aapoint_stage); + +   draw_alloc_temp_verts( &aapoint->stage, 4 ); + +   aapoint->stage.draw = draw; +   aapoint->stage.next = NULL; +   aapoint->stage.point = aapoint_first_point; +   aapoint->stage.line = passthrough_line; +   aapoint->stage.tri = passthrough_tri; +   aapoint->stage.flush = aapoint_flush; +   aapoint->stage.reset_stipple_counter = aapoint_reset_stipple_counter; +   aapoint->stage.destroy = aapoint_destroy; + +   return aapoint; +} + + +/* + * XXX temporary? solution to mapping a pipe_context to a aapoint_stage. + */ + +#define MAX_CONTEXTS 10 + +static struct pipe_context *Pipe[MAX_CONTEXTS]; +static struct aapoint_stage *Stage[MAX_CONTEXTS]; +static uint NumContexts; + +static void +add_aa_pipe_context(struct pipe_context *pipe, struct aapoint_stage *aa) +{ +   assert(NumContexts < MAX_CONTEXTS); +   Pipe[NumContexts] = pipe; +   Stage[NumContexts] = aa; +   NumContexts++; +} + +static struct aapoint_stage * +aapoint_stage_from_pipe(struct pipe_context *pipe) +{ +   uint i; +   for (i = 0; i < NumContexts; i++) { +      if (Pipe[i] == pipe) +         return Stage[i]; +   } +   assert(0); +   return NULL; +} + + +/** + * This function overrides the driver's create_fs_state() function and + * will typically be called by the state tracker. + */ +static void * +aapoint_create_fs_state(struct pipe_context *pipe, +                       const struct pipe_shader_state *fs) +{ +   struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe); +   struct aapoint_fragment_shader *aafs = CALLOC_STRUCT(aapoint_fragment_shader); + +   if (aafs) { +      aafs->state = *fs; + +      /* pass-through */ +      aafs->driver_fs = aapoint->driver_create_fs_state(aapoint->pipe, fs); +   } + +   return aafs; +} + + +static void +aapoint_bind_fs_state(struct pipe_context *pipe, void *fs) +{ +   struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe); +   struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs; +   /* save current */ +   aapoint->fs = aafs; +   /* pass-through */ +   aapoint->driver_bind_fs_state(aapoint->pipe, aafs->driver_fs); +} + + +static void +aapoint_delete_fs_state(struct pipe_context *pipe, void *fs) +{ +   struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe); +   struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs; +   /* pass-through */ +   aapoint->driver_delete_fs_state(aapoint->pipe, aafs->driver_fs); +   FREE(aafs); +} + + +/** + * 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. + */ +void +draw_install_aapoint_stage(struct draw_context *draw, +                           struct pipe_context *pipe) +{ +   struct aapoint_stage *aapoint; + +   /* +    * Create / install AA point drawing / prim stage +    */ +   aapoint = draw_aapoint_stage( draw ); +   assert(aapoint); +   draw->pipeline.aapoint = &aapoint->stage; + +   aapoint->pipe = pipe; + +   /* save original driver functions */ +   aapoint->driver_create_fs_state = pipe->create_fs_state; +   aapoint->driver_bind_fs_state = pipe->bind_fs_state; +   aapoint->driver_delete_fs_state = pipe->delete_fs_state; + +   /* override the driver's functions */ +   pipe->create_fs_state = aapoint_create_fs_state; +   pipe->bind_fs_state = aapoint_bind_fs_state; +   pipe->delete_fs_state = aapoint_delete_fs_state; + +   add_aa_pipe_context(pipe, aapoint); +} diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 4be3830316..c28e78d33a 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -72,10 +72,10 @@ struct draw_context *draw_create( void )     {        uint i;        const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f; -      char *tmp = align_malloc(Elements(draw->vcache.vertex) * size, 16); +      char *tmp = align_malloc(Elements(draw->vs.queue) * size, 16); -      for (i = 0; i < Elements(draw->vcache.vertex); i++) -	 draw->vcache.vertex[i] = (struct vertex_header *)(tmp + i * size); +      for (i = 0; i < Elements(draw->vs.queue); i++) +	 draw->vs.queue[i].vertex = (struct vertex_header *)(tmp + i * size);     }     draw->shader_queue_flush = draw_vertex_shader_queue_flush; @@ -103,10 +103,14 @@ void draw_destroy( struct draw_context *draw )     draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );     draw->pipeline.cull->destroy( draw->pipeline.cull );     draw->pipeline.validate->destroy( draw->pipeline.validate ); +   if (draw->pipeline.aaline) +      draw->pipeline.aaline->destroy( draw->pipeline.aaline ); +   if (draw->pipeline.aapoint) +      draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );     if (draw->pipeline.rasterize)        draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );     tgsi_exec_machine_free_data(&draw->machine); -   align_free( draw->vcache.vertex[0] ); /* Frees all the vertices. */ +   align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */     FREE( draw );  } @@ -240,6 +244,26 @@ draw_convert_wide_lines(struct draw_context *draw, boolean enable)  /** + * The draw module may sometimes generate vertices with extra attributes + * (such as texcoords for AA lines).  The driver can call this function + * to find those attributes. + */ +int +draw_find_vs_output(struct draw_context *draw, +                    uint semantic_name, uint semantic_index) +{ +   /* XXX there may be more than one extra vertex attrib. +    * For example, simulated gl_FragCoord and gl_PointCoord. +    */ +   if (draw->extra_vp_outputs.semantic_name == semantic_name && +       draw->extra_vp_outputs.semantic_index == semantic_index) { +      return draw->extra_vp_outputs.slot; +   } +   return 0; +} + + +/**   * Allocate space for temporary post-transform vertices, such as for clipping.   */  void draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr ) diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index ddeb184497..c25301f71d 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -41,6 +41,7 @@  #include "pipe/p_state.h" +struct pipe_context;  struct vertex_buffer;  struct vertex_info;  struct draw_context; @@ -93,6 +94,26 @@ void draw_convert_wide_points(struct draw_context *draw, boolean enable);  void draw_convert_wide_lines(struct draw_context *draw, boolean enable); +boolean draw_use_sse(struct draw_context *draw); + +void +draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe); + +void +draw_install_aapoint_stage(struct draw_context *draw, struct pipe_context *pipe); + +void +draw_install_pstipple_stage(struct draw_context *draw, struct pipe_context *pipe); + + +int +draw_find_vs_output(struct draw_context *draw, +                    uint semantic_name, uint semantic_index); + + +/* + * Vertex shader functions + */  struct draw_vertex_shader *  draw_create_vertex_shader(struct draw_context *draw, @@ -102,7 +123,11 @@ void draw_bind_vertex_shader(struct draw_context *draw,  void draw_delete_vertex_shader(struct draw_context *draw,                                 struct draw_vertex_shader *dvs); -boolean draw_use_sse(struct draw_context *draw); + + +/* + * Vertex data functions + */  void draw_set_vertex_buffer(struct draw_context *draw,  			    unsigned attr, diff --git a/src/gallium/auxiliary/draw/draw_prim.c b/src/gallium/auxiliary/draw/draw_prim.c index 51e2242719..7d6cd43410 100644 --- a/src/gallium/auxiliary/draw/draw_prim.c +++ b/src/gallium/auxiliary/draw/draw_prim.c @@ -114,6 +114,7 @@ static void draw_prim_queue_flush( struct draw_context *draw )     }     draw->pq.queue_nr = 0;    +   draw->vs.post_nr = 0;        draw_vertex_cache_unreference( draw );  } @@ -121,11 +122,15 @@ static void draw_prim_queue_flush( struct draw_context *draw )  void draw_do_flush( struct draw_context *draw, unsigned flags )  { +   static boolean flushing = FALSE; +     if (0)        debug_printf("Flushing with %d verts, %d prims\n",                     draw->vs.queue_nr,                     draw->pq.queue_nr ); +   if (!flushing) { +      flushing = TRUE;     if (flags >= DRAW_FLUSH_SHADER_QUEUE) {        if (draw->vs.queue_nr) @@ -146,6 +151,9 @@ void draw_do_flush( struct draw_context *draw, unsigned flags )  	 }        }         } + +      flushing = FALSE; +   }  } @@ -219,6 +227,7 @@ static void do_triangle( struct draw_context *draw,  {     struct prim_header *prim = get_queued_prim( draw, 3 ); +//   _mesa_printf("tri %d %d %d\n", i0, i1, i2);     prim->reset_line_stipple = 1;     prim->edgeflags = ~0;     prim->pad = 0; diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index bc11259cb2..6abced139b 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -44,10 +44,11 @@  #include "pipe/p_state.h"  #include "pipe/p_defines.h" -#include "x86/rtasm/x86sse.h" +#include "rtasm/rtasm_x86sse.h"  #include "tgsi/exec/tgsi_exec.h" +struct pipe_context;  struct gallivm_prog;  struct gallivm_cpu_engine; @@ -119,7 +120,7 @@ struct draw_stage  }; -#define PRIM_QUEUE_LENGTH      16 +#define PRIM_QUEUE_LENGTH      32  #define VCACHE_SIZE            32  #define VCACHE_OVERFLOW        4  #define VS_QUEUE_LENGTH        (VCACHE_SIZE + VCACHE_OVERFLOW + 1)	/* can never fill up */ @@ -179,6 +180,9 @@ struct draw_context        struct draw_stage *offset;        struct draw_stage *unfilled;        struct draw_stage *stipple; +      struct draw_stage *aapoint; +      struct draw_stage *aaline; +      struct draw_stage *pstipple;        struct draw_stage *wide;        struct draw_stage *rasterize;     } pipeline; @@ -212,9 +216,17 @@ struct draw_context     unsigned nr_planes;     boolean convert_wide_points; /**< convert wide points to tris? */ -   boolean convert_wide_lines;  /**< convert side lines to tris? */ +   boolean convert_wide_lines;  /**< convert wide lines to tris? */     boolean use_sse; +   /* If a prim stage introduces new vertex attributes, they'll be stored here +    */ +   struct { +      uint semantic_name; +      uint semantic_index; +      int slot; +   } extra_vp_outputs; +     unsigned reduced_prim;     /** TGSI program interpreter runtime state */ @@ -234,8 +246,12 @@ struct draw_context      */     struct {        unsigned referenced;  /**< bitfield */ -      unsigned idx[VCACHE_SIZE + VCACHE_OVERFLOW]; -      struct vertex_header *vertex[VCACHE_SIZE + VCACHE_OVERFLOW]; + +      struct { +	 unsigned in;		/* client array element */ +	 unsigned out;		/* index in vs queue/array */ +      } idx[VCACHE_SIZE + VCACHE_OVERFLOW]; +        unsigned overflow;        /** To find space in the vertex cache: */ @@ -248,9 +264,10 @@ struct draw_context     struct {        struct {  	 unsigned elt;   /**< index into the user's vertex arrays */ -	 struct vertex_header *dest; /**< points into vcache.vertex[] array */ +	 struct vertex_header *vertex;        } queue[VS_QUEUE_LENGTH];        unsigned queue_nr; +      unsigned post_nr;     } vs;     /** diff --git a/src/gallium/auxiliary/draw/draw_pstipple.c b/src/gallium/auxiliary/draw/draw_pstipple.c new file mode 100644 index 0000000000..4048abf856 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pstipple.c @@ -0,0 +1,717 @@ +/************************************************************************** + *  + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *  + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *  + **************************************************************************/ + +/** + * Polygon stipple stage:  implement polygon stipple with texture map and + * fragment program.  The fragment program samples the texture and does + * a fragment kill for the stipple-failing fragments. + * + * Authors:  Brian Paul + */ + + +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_shader_tokens.h" + +#include "tgsi/util/tgsi_transform.h" +#include "tgsi/util/tgsi_dump.h" + +#include "draw_context.h" +#include "draw_private.h" + + + +/** + * Subclass of pipe_shader_state to carry extra fragment shader info. + */ +struct pstip_fragment_shader +{ +   struct pipe_shader_state state; +   void *driver_fs; +   void *pstip_fs; +}; + + +/** + * Subclass of draw_stage + */ +struct pstip_stage +{ +   struct draw_stage stage; + +   void *sampler_cso; +   struct pipe_texture *texture; +   uint sampler_unit; + +   /* +    * Currently bound state +    */ +   struct pstip_fragment_shader *fs; +   struct { +      void *sampler[PIPE_MAX_SAMPLERS]; +      struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; +      const struct pipe_poly_stipple *stipple; +   } state; + +   /* +    * Driver interface/override functions +    */ +   void * (*driver_create_fs_state)(struct pipe_context *, +                                    const struct pipe_shader_state *); +   void (*driver_bind_fs_state)(struct pipe_context *, void *); +   void (*driver_delete_fs_state)(struct pipe_context *, void *); + +   void (*driver_bind_sampler_state)(struct pipe_context *, unsigned, void *); + +   void (*driver_set_sampler_texture)(struct pipe_context *, +                                      unsigned sampler, +                                      struct pipe_texture *); + +   void (*driver_set_polygon_stipple)(struct pipe_context *, +                                      const struct pipe_poly_stipple *); + +   struct pipe_context *pipe; +}; + + + +/** + * Subclass of tgsi_transform_context, used for transforming the + * user's fragment shader to add the special AA instructions. + */ +struct pstip_transform_context { +   struct tgsi_transform_context base; +   uint tempsUsed;  /**< bitmask */ +   int wincoordInput; +   int maxInput; +   int maxSampler;  /**< max sampler index found */ +   int texTemp;  /**< temp registers */ +   int numImmed; +   boolean firstInstruction; +}; + + +/** + * TGSI declaration transform callback. + * Look for a free sampler, a free input attrib, and two free temp regs. + */ +static void +pstip_transform_decl(struct tgsi_transform_context *ctx, +                     struct tgsi_full_declaration *decl) +{ +   struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx; + +   if (decl->Declaration.File == TGSI_FILE_SAMPLER) { +      if ((int) decl->u.DeclarationRange.Last > pctx->maxSampler) +         pctx->maxSampler = (int) decl->u.DeclarationRange.Last; +   } +   else if (decl->Declaration.File == TGSI_FILE_INPUT) { +      pctx->maxInput = MAX2(pctx->maxInput, decl->u.DeclarationRange.Last); +      if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION) +         pctx->wincoordInput = (int) decl->u.DeclarationRange.First; +   } +   else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { +      uint i; +      for (i = decl->u.DeclarationRange.First; +           i <= decl->u.DeclarationRange.Last; i++) { +         pctx->tempsUsed |= (1 << i); +      } +   } + +   ctx->emit_declaration(ctx, decl); +} + + +static void +pstip_transform_immed(struct tgsi_transform_context *ctx, +                      struct tgsi_full_immediate *immed) +{ +   struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx; +   pctx->numImmed++; +} + + +/** + * TGSI instruction transform callback. + * Replace writes to result.color w/ a temp reg. + * Upon END instruction, insert texture sampling code for antialiasing. + */ +static void +pstip_transform_inst(struct tgsi_transform_context *ctx, +                     struct tgsi_full_instruction *inst) +{ +   struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx; + +   if (pctx->firstInstruction) { +      /* emit our new declarations before the first instruction */ + +      struct tgsi_full_declaration decl; +      struct tgsi_full_instruction newInst; +      uint i; +      int wincoordInput; +      const int sampler = pctx->maxSampler + 1; + +      if (pctx->wincoordInput < 0) +         wincoordInput = pctx->maxInput + 1; +      else +         wincoordInput = pctx->wincoordInput; + +      /* find one free temp reg */ +      for (i = 0; i < 32; i++) { +         if ((pctx->tempsUsed & (1 << i)) == 0) { +            /* found a free temp */ +            if (pctx->texTemp < 0) +               pctx->texTemp  = i; +            else +               break; +         } +      } +      assert(pctx->texTemp >= 0); + +      if (pctx->wincoordInput < 0) { +         /* declare new position input reg */ +         decl = tgsi_default_full_declaration(); +         decl.Declaration.File = TGSI_FILE_INPUT; +         decl.Declaration.Semantic = 1; +         decl.Semantic.SemanticName = TGSI_SEMANTIC_POSITION; +         decl.Semantic.SemanticIndex = 0; +         decl.Declaration.Interpolate = 1; +         decl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR; /* XXX? */ +         decl.u.DeclarationRange.First =  +            decl.u.DeclarationRange.Last = wincoordInput; +         ctx->emit_declaration(ctx, &decl); +      } + +      /* declare new sampler */ +      decl = tgsi_default_full_declaration(); +      decl.Declaration.File = TGSI_FILE_SAMPLER; +      decl.u.DeclarationRange.First =  +      decl.u.DeclarationRange.Last = sampler; +      ctx->emit_declaration(ctx, &decl); + +      /* declare new temp regs */ +      decl = tgsi_default_full_declaration(); +      decl.Declaration.File = TGSI_FILE_TEMPORARY; +      decl.u.DeclarationRange.First =  +      decl.u.DeclarationRange.Last = pctx->texTemp; +      ctx->emit_declaration(ctx, &decl); + +      /* emit immediate = {1/32, 1/32, 1, 1} +       * The index/position of this immediate will be pctx->numImmed +       */ +      { +         static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 }; +         struct tgsi_full_immediate immed; +         uint size = 4; +         immed = tgsi_default_full_immediate(); +         immed.Immediate.Size = 1 + size; /* one for the token itself */ +         immed.u.ImmediateFloat32 = (struct tgsi_immediate_float32 *) value; +         ctx->emit_immediate(ctx, &immed); +      } + +      pctx->firstInstruction = FALSE; + + +      /*  +       * Insert new MUL/TEX/KILP instructions at start of program +       * Take gl_FragCoord, divide by 32 (stipple size), sample the +       * texture and kill fragment if needed. +       * +       * We'd like to use non-normalized texcoords to index into a RECT +       * texture, but we can only use GL_REPEAT wrap mode with normalized +       * texcoords.  Darn. +       */ + +      /* MUL texTemp, INPUT[wincoord], 1/32; */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_MUL; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullDstRegisters[0].DstRegister.Index = pctx->texTemp; +      newInst.Instruction.NumSrcRegs = 2; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; +      newInst.FullSrcRegisters[0].SrcRegister.Index = wincoordInput; +      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_IMMEDIATE; +      newInst.FullSrcRegisters[1].SrcRegister.Index = pctx->numImmed; +      ctx->emit_instruction(ctx, &newInst); + +      /* TEX texTemp, texTemp, sampler; */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_TEX; +      newInst.Instruction.NumDstRegs = 1; +      newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullDstRegisters[0].DstRegister.Index = pctx->texTemp; +      newInst.Instruction.NumSrcRegs = 2; +      newInst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = pctx->texTemp; +      newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; +      newInst.FullSrcRegisters[1].SrcRegister.Index = sampler; +      ctx->emit_instruction(ctx, &newInst); + +      /* KILP texTemp;   # if texTemp < 0, KILL fragment */ +      newInst = tgsi_default_full_instruction(); +      newInst.Instruction.Opcode = TGSI_OPCODE_KILP; +      newInst.Instruction.NumDstRegs = 0; +      newInst.Instruction.NumSrcRegs = 1; +      newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; +      newInst.FullSrcRegisters[0].SrcRegister.Index = pctx->texTemp; +      newInst.FullSrcRegisters[0].SrcRegister.Negate = 1; +      ctx->emit_instruction(ctx, &newInst); +   } + +   /* emit this instruction */ +   ctx->emit_instruction(ctx, inst); +} + + +/** + * Generate the frag shader we'll use for doing polygon stipple. + * This will be the user's shader prefixed with a TEX and KIL instruction. + */ +static void +generate_pstip_fs(struct pstip_stage *pstip) +{ +   const struct pipe_shader_state *orig_fs = &pstip->fs->state; +   /*struct draw_context *draw = pstip->stage.draw;*/ +   struct pipe_shader_state pstip_fs; +   struct pstip_transform_context transform; + +#define MAX 1000 + +   pstip_fs = *orig_fs; /* copy to init */ +   pstip_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX); + +   memset(&transform, 0, sizeof(transform)); +   transform.wincoordInput = -1; +   transform.maxInput = -1; +   transform.maxSampler = -1; +   transform.texTemp = -1; +   transform.firstInstruction = TRUE; +   transform.base.transform_instruction = pstip_transform_inst; +   transform.base.transform_declaration = pstip_transform_decl; +   transform.base.transform_immediate = pstip_transform_immed; + +   tgsi_transform_shader(orig_fs->tokens, +                         (struct tgsi_token *) pstip_fs.tokens, +                         MAX, &transform.base); + +#if 1 /* DEBUG */ +   tgsi_dump(orig_fs->tokens, 0); +   tgsi_dump(pstip_fs.tokens, 0); +#endif + +   pstip->sampler_unit = transform.maxSampler + 1; + +   if (transform.wincoordInput < 0) { +      pstip_fs.input_semantic_name[pstip_fs.num_inputs] = TGSI_SEMANTIC_POSITION; +      pstip_fs.input_semantic_index[pstip_fs.num_inputs] = transform.maxInput; +      pstip_fs.num_inputs++; +   } + +   pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs); +} + + +/** + * Load texture image with current stipple pattern. + */ +static void +pstip_update_texture(struct pstip_stage *pstip) +{ +   static const uint bit31 = 1 << 31; +   struct pipe_context *pipe = pstip->pipe; +   struct pipe_surface *surface; +   const uint *stipple = pstip->state.stipple->stipple; +   uint i, j; +   ubyte *data; + +   surface = pipe->get_tex_surface(pipe, pstip->texture, 0, 0, 0); +   data = pipe_surface_map(surface); + +   /* +    * Load alpha texture. +    * Note: 0 means keep the fragment, 255 means kill it. +    * We'll negate the texel value and use KILP which kills if value +    * is negative. +    */ +   for (i = 0; i < 32; i++) { +      for (j = 0; j < 32; j++) { +         if (stipple[i] & (bit31 >> j)) { +            /* fragment "on" */ +            data[i * surface->pitch + j] = 0; +         } +         else { +            /* fragment "off" */ +            data[i * surface->pitch + j] = 255; +         } +      } +   } + +   /* unmap */ +   pipe_surface_unmap(surface); +   pipe_surface_reference(&surface, NULL); +   pipe->texture_update(pipe, pstip->texture); +} + + +/** + * Create the texture map we'll use for stippling. + */ +static void +pstip_create_texture(struct pstip_stage *pstip) +{ +   struct pipe_context *pipe = pstip->pipe; +   struct pipe_texture texTemp; + +   memset(&texTemp, 0, sizeof(texTemp)); +   texTemp.target = PIPE_TEXTURE_2D; +   texTemp.format = PIPE_FORMAT_U_A8; /* XXX verify supported by driver! */ +   texTemp.last_level = 0; +   texTemp.width[0] = 32; +   texTemp.height[0] = 32; +   texTemp.depth[0] = 1; +   texTemp.cpp = 1; + +   pstip->texture = pipe->texture_create(pipe, &texTemp); + +   //pstip_update_texture(pstip); +} + + +/** + * Create the sampler CSO that'll be used for antialiasing. + * By using a mipmapped texture, we don't have to generate a different + * texture image for each line size. + */ +static void +pstip_create_sampler(struct pstip_stage *pstip) +{ +   struct pipe_sampler_state sampler; +   struct pipe_context *pipe = pstip->pipe; + +   memset(&sampler, 0, sizeof(sampler)); +   sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; +   sampler.wrap_t = PIPE_TEX_WRAP_REPEAT; +   sampler.wrap_r = PIPE_TEX_WRAP_REPEAT; +   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; +   sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; +   sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; +   sampler.normalized_coords = 1; +   sampler.min_lod = 0.0f; +   sampler.max_lod = 0.0f; + +   pstip->sampler_cso = pipe->create_sampler_state(pipe, &sampler); +} + + +/** + * When we're about to draw our first AA line in a batch, this function is + * called to tell the driver to bind our modified fragment shader. + */ +static void +bind_pstip_fragment_shader(struct pstip_stage *pstip) +{ +   if (!pstip->fs->pstip_fs) { +      generate_pstip_fs(pstip); +   } +   pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs); +} + + + +static INLINE struct pstip_stage * +pstip_stage( struct draw_stage *stage ) +{ +   return (struct pstip_stage *) stage; +} + + +static void +passthrough_point(struct draw_stage *stage, struct prim_header *header) +{ +   stage->next->point(stage->next, header); +} + + +static void +passthrough_line(struct draw_stage *stage, struct prim_header *header) +{ +   stage->next->line(stage->next, header); +} + + +static void +passthrough_tri(struct draw_stage *stage, struct prim_header *header) +{ +   stage->next->tri(stage->next, header); +} + + + +static void +pstip_first_tri(struct draw_stage *stage, struct prim_header *header) +{ +   struct pstip_stage *pstip = pstip_stage(stage); +   struct draw_context *draw = stage->draw; +   struct pipe_context *pipe = pstip->pipe; + +   assert(draw->rasterizer->poly_stipple_enable); + +   /* +    * Bind our fragprog, sampler and texture +    */ +   bind_pstip_fragment_shader(pstip); + +   pstip->driver_bind_sampler_state(pipe, pstip->sampler_unit, pstip->sampler_cso); +   pstip->driver_set_sampler_texture(pipe, pstip->sampler_unit, pstip->texture); + +   /* now really draw first line */ +   stage->tri = passthrough_tri; +   stage->tri(stage, header); +} + + +static void +pstip_flush(struct draw_stage *stage, unsigned flags) +{ +   /*struct draw_context *draw = stage->draw;*/ +   struct pstip_stage *pstip = pstip_stage(stage); +   struct pipe_context *pipe = pstip->pipe; + +   stage->tri = pstip_first_tri; +   stage->next->flush( stage->next, flags ); + +   /* restore original frag shader */ +   pstip->driver_bind_fs_state(pipe, pstip->fs->driver_fs); + +   /* XXX restore original texture, sampler state */ +   pstip->driver_bind_sampler_state(pipe, pstip->sampler_unit, +                                 pstip->state.sampler[pstip->sampler_unit]); +   pstip->driver_set_sampler_texture(pipe, pstip->sampler_unit, +                                 pstip->state.texture[pstip->sampler_unit]); +} + + +static void +pstip_reset_stipple_counter(struct draw_stage *stage) +{ +   stage->next->reset_stipple_counter( stage->next ); +} + + +static void +pstip_destroy(struct draw_stage *stage) +{ +   draw_free_temp_verts( stage ); +   FREE( stage ); +} + + +static struct pstip_stage * +draw_pstip_stage(struct draw_context *draw) +{ +   struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage); + +   draw_alloc_temp_verts( &pstip->stage, 8 ); + +   pstip->stage.draw = draw; +   pstip->stage.next = NULL; +   pstip->stage.point = passthrough_point; +   pstip->stage.line = passthrough_line; +   pstip->stage.tri = pstip_first_tri; +   pstip->stage.flush = pstip_flush; +   pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter; +   pstip->stage.destroy = pstip_destroy; + +   return pstip; +} + + +/* + * XXX temporary? solution to mapping a pipe_context to a pstip_stage. + */ + +#define MAX_CONTEXTS 10 + +static struct pipe_context *Pipe[MAX_CONTEXTS]; +static struct pstip_stage *Stage[MAX_CONTEXTS]; +static uint NumContexts; + +static void +add_pstip_pipe_context(struct pipe_context *pipe, struct pstip_stage *pstip) +{ +   assert(NumContexts < MAX_CONTEXTS); +   Pipe[NumContexts] = pipe; +   Stage[NumContexts] = pstip; +   NumContexts++; +} + +static struct pstip_stage * +pstip_stage_from_pipe(struct pipe_context *pipe) +{ +   uint i; +   for (i = 0; i < NumContexts; i++) { +      if (Pipe[i] == pipe) +         return Stage[i]; +   } +   assert(0); +   return NULL; +} + + +/** + * This function overrides the driver's create_fs_state() function and + * will typically be called by the state tracker. + */ +static void * +pstip_create_fs_state(struct pipe_context *pipe, +                       const struct pipe_shader_state *fs) +{ +   struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); +   struct pstip_fragment_shader *aafs = CALLOC_STRUCT(pstip_fragment_shader); + +   if (aafs) { +      aafs->state = *fs; + +      /* pass-through */ +      aafs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs); +   } + +   return aafs; +} + + +static void +pstip_bind_fs_state(struct pipe_context *pipe, void *fs) +{ +   struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); +   struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs; +   /* save current */ +   pstip->fs = aafs; +   /* pass-through */ +   pstip->driver_bind_fs_state(pstip->pipe, aafs->driver_fs); +} + + +static void +pstip_delete_fs_state(struct pipe_context *pipe, void *fs) +{ +   struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); +   struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs; +   /* pass-through */ +   pstip->driver_delete_fs_state(pstip->pipe, aafs->driver_fs); +   FREE(aafs); +} + + +static void +pstip_bind_sampler_state(struct pipe_context *pipe, +                         unsigned unit, void *sampler) +{ +   struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); +   /* save current */ +   pstip->state.sampler[unit] = sampler; +   /* pass-through */ +   pstip->driver_bind_sampler_state(pstip->pipe, unit, sampler); +} + + +static void +pstip_set_sampler_texture(struct pipe_context *pipe, +                          unsigned sampler, struct pipe_texture *texture) +{ +   struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); +   /* save current */ +   pstip->state.texture[sampler] = texture; +   /* pass-through */ +   pstip->driver_set_sampler_texture(pstip->pipe, sampler, texture); +} + + +static void +pstip_set_polygon_stipple(struct pipe_context *pipe, +                          const struct pipe_poly_stipple *stipple) +{ +   struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); +   /* save current */ +   pstip->state.stipple = stipple; +   /* pass-through */ +   pstip->driver_set_polygon_stipple(pstip->pipe, stipple); + +   pstip_update_texture(pstip); +} + + + +/** + * Called by drivers that want to install this AA line prim stage + * into the draw module's pipeline.  This will not be used if the + * hardware has native support for AA lines. + */ +void +draw_install_pstipple_stage(struct draw_context *draw, +                            struct pipe_context *pipe) +{ +   struct pstip_stage *pstip; + +   /* +    * Create / install AA line drawing / prim stage +    */ +   pstip = draw_pstip_stage( draw ); +   assert(pstip); +   draw->pipeline.pstipple = &pstip->stage; + +   pstip->pipe = pipe; + +   /* create special texture, sampler state */ +   pstip_create_texture(pstip); +   pstip_create_sampler(pstip); + +   /* save original driver functions */ +   pstip->driver_create_fs_state = pipe->create_fs_state; +   pstip->driver_bind_fs_state = pipe->bind_fs_state; +   pstip->driver_delete_fs_state = pipe->delete_fs_state; + +   pstip->driver_bind_sampler_state = pipe->bind_sampler_state; +   pstip->driver_set_sampler_texture = pipe->set_sampler_texture; +   pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple; + +   /* override the driver's functions */ +   pipe->create_fs_state = pstip_create_fs_state; +   pipe->bind_fs_state = pstip_bind_fs_state; +   pipe->delete_fs_state = pstip_delete_fs_state; + +   pipe->bind_sampler_state = pstip_bind_sampler_state; +   pipe->set_sampler_texture = pstip_set_sampler_texture; +   pipe->set_polygon_stipple = pstip_set_polygon_stipple; + +   add_pstip_pipe_context(pipe, pstip); +} diff --git a/src/gallium/auxiliary/draw/draw_validate.c b/src/gallium/auxiliary/draw/draw_validate.c index 4375ebabbc..efd6793f2b 100644 --- a/src/gallium/auxiliary/draw/draw_validate.c +++ b/src/gallium/auxiliary/draw/draw_validate.c @@ -58,7 +58,18 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )      * shorter pipelines for lines & points.      */ -   if ((draw->rasterizer->line_width != 1.0 && draw->convert_wide_lines) || +   if (draw->rasterizer->line_smooth && draw->pipeline.aaline) { +      draw->pipeline.aaline->next = next; +      next = draw->pipeline.aaline; +   } + +   if (draw->rasterizer->point_smooth && draw->pipeline.aapoint) { +      draw->pipeline.aapoint->next = next; +      next = draw->pipeline.aapoint; +   } + +   if ((draw->rasterizer->line_width != 1.0 && draw->convert_wide_lines +        && !draw->rasterizer->line_smooth) ||         (draw->rasterizer->point_size != 1.0 && draw->convert_wide_points) ||         draw->rasterizer->point_sprite) {        draw->pipeline.wide->next = next; @@ -71,6 +82,12 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )        precalc_flat = 1;		/* only needed for lines really */     } +   if (draw->rasterizer->poly_stipple_enable +       && draw->pipeline.pstipple) { +      draw->pipeline.pstipple->next = next; +      next = draw->pipeline.pstipple; +   } +     if (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||         draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) {        draw->pipeline.unfilled->next = next; diff --git a/src/gallium/auxiliary/draw/draw_vertex_cache.c b/src/gallium/auxiliary/draw/draw_vertex_cache.c index 44427999cc..53f8bbec44 100644 --- a/src/gallium/auxiliary/draw/draw_vertex_cache.c +++ b/src/gallium/auxiliary/draw/draw_vertex_cache.c @@ -41,7 +41,7 @@ void draw_vertex_cache_invalidate( struct draw_context *draw )     assert(draw->vs.queue_nr == 0);     assert(draw->vcache.referenced == 0); -   memset(draw->vcache.idx, ~0, sizeof(draw->vcache.idx)); +//   memset(draw->vcache.idx, ~0, sizeof(draw->vcache.idx));  } @@ -62,43 +62,51 @@ static struct vertex_header *get_vertex( struct draw_context *draw,     assert(slot < 32); /* so we don't exceed the bitfield size below */ -   /* Cache miss? -    */ -   if (draw->vcache.idx[slot] != i) { - -      /* If slot is in use, use the overflow area: +   if (draw->vcache.referenced & (1<<slot)) +   { +      /* Cache hit?         */ -      if (draw->vcache.referenced & (1 << slot)) { -	 slot = VCACHE_SIZE + draw->vcache.overflow++; +      if (draw->vcache.idx[slot].in == i) { +//	 _mesa_printf("HIT %d %d\n", slot, i); +	 assert(draw->vcache.idx[slot].out < draw->vs.queue_nr); +	 return draw->vs.queue[draw->vcache.idx[slot].out].vertex;        } +      /* Otherwise a collision +       */ +      slot = VCACHE_SIZE + draw->vcache.overflow++; +//      _mesa_printf("XXX %d --> %d\n", i, slot); +   } + +   /* Deal with the cache miss:  +    */ +   { +      unsigned out; +              assert(slot < Elements(draw->vcache.idx)); -      draw->vcache.idx[slot] = i; +//      _mesa_printf("NEW %d %d\n", slot, i); +      draw->vcache.idx[slot].in = i; +      draw->vcache.idx[slot].out = out = draw->vs.queue_nr++; +      draw->vcache.referenced |= (1 << slot); +        /* Add to vertex shader queue:         */        assert(draw->vs.queue_nr < VS_QUEUE_LENGTH); -      draw->vs.queue[draw->vs.queue_nr].dest = draw->vcache.vertex[slot]; -      draw->vs.queue[draw->vs.queue_nr].elt = i; -      draw->vs.queue_nr++; + +      draw->vs.queue[out].elt = i; +      draw->vs.queue[out].vertex->clipmask = 0; +      draw->vs.queue[out].vertex->edgeflag = 1; /*XXX use user's edge flag! */ +      draw->vs.queue[out].vertex->pad = 0; +      draw->vs.queue[out].vertex->vertex_id = UNDEFINED_VERTEX_ID;        /* Need to set the vertex's edge flag here.  If we're being called         * by do_ef_triangle(), that function needs edge flag info!         */ -      draw->vcache.vertex[slot]->clipmask = 0; -      draw->vcache.vertex[slot]->edgeflag = 1; /*XXX use user's edge flag! */ -      draw->vcache.vertex[slot]->pad = 0; -      draw->vcache.vertex[slot]->vertex_id = UNDEFINED_VERTEX_ID; -   } - -   /* primitive flushing may have cleared the bitfield but did not -    * clear the idx[] array values.  Set the bit now.  This fixes a -    * bug found when drawing long triangle fans. -    */ -   draw->vcache.referenced |= (1 << slot); -   return draw->vcache.vertex[slot]; +      return draw->vs.queue[draw->vcache.idx[slot].out].vertex; +   }  } @@ -130,8 +138,8 @@ void draw_vertex_cache_reset_vertex_ids( struct draw_context *draw )  {     unsigned i; -   for (i = 0; i < Elements(draw->vcache.vertex); i++) -      draw->vcache.vertex[i]->vertex_id = UNDEFINED_VERTEX_ID; +   for (i = 0; i < draw->vs.post_nr; i++) +      draw->vs.queue[i].vertex->vertex_id = UNDEFINED_VERTEX_ID;  } diff --git a/src/gallium/auxiliary/draw/draw_vertex_shader.c b/src/gallium/auxiliary/draw/draw_vertex_shader.c index f68f6e3244..5d2f5c9c43 100644 --- a/src/gallium/auxiliary/draw/draw_vertex_shader.c +++ b/src/gallium/auxiliary/draw/draw_vertex_shader.c @@ -55,7 +55,7 @@ draw_vertex_shader_queue_flush(struct draw_context *draw)      */     shader->prepare( shader, draw ); -//   fprintf(stderr, " q(%d) ", draw->vs.queue_nr ); +//   fprintf(stderr, "%s %d\n", __FUNCTION__, draw->vs.queue_nr );     /* run vertex shader on vertex cache entries, four per invokation */     for (i = 0; i < draw->vs.queue_nr; i += 4) { @@ -65,12 +65,12 @@ draw_vertex_shader_queue_flush(struct draw_context *draw)        for (j = 0; j < n; j++) {           elts[j] = draw->vs.queue[i + j].elt; -         dests[j] = draw->vs.queue[i + j].dest; +         dests[j] = draw->vs.queue[i + j].vertex;        }        for ( ; j < 4; j++) {  	 elts[j] = elts[0]; -	 dests[j] = dests[0]; +         dests[j] = draw->vs.queue[i + j].vertex;        }        assert(n > 0); @@ -79,6 +79,7 @@ draw_vertex_shader_queue_flush(struct draw_context *draw)        shader->run(shader, draw, elts, n, dests);     } +   draw->vs.post_nr = draw->vs.queue_nr;     draw->vs.queue_nr = 0;  } diff --git a/src/gallium/auxiliary/draw/draw_vf.c b/src/gallium/auxiliary/draw/draw_vf.c index dc3a5ecd21..901ff20a7e 100644 --- a/src/gallium/auxiliary/draw/draw_vf.c +++ b/src/gallium/auxiliary/draw/draw_vf.c @@ -30,6 +30,7 @@  #include "pipe/p_compiler.h"  #include "pipe/p_util.h" +#include "rtasm/rtasm_execmem.h"  #include "draw_vf.h" @@ -37,11 +38,6 @@  #define DRAW_VF_DBG 0 -/* TODO: remove this */ -extern void  -_mesa_exec_free( void *addr ); - -  static boolean match_fastpath( struct draw_vertex_fetch *vf,  				 const struct draw_vf_fastpath *fp)  { @@ -414,12 +410,12 @@ void draw_vf_destroy( struct draw_vertex_fetch *vf )        FREE(fp->attr);        /* KW: At the moment, fp->func is constrained to be allocated by -       * _mesa_exec_alloc(), as the hardwired fastpaths in +       * rtasm_exec_alloc(), as the hardwired fastpaths in         * t_vertex_generic.c are handled specially.  It would be nice         * to unify them, but this probably won't change until this         * module gets another overhaul.         */ -      //_mesa_exec_free((void *) fp->func); +      //rtasm_exec_free((void *) fp->func);        FREE(fp);     } diff --git a/src/gallium/auxiliary/draw/draw_vf_sse.c b/src/gallium/auxiliary/draw/draw_vf_sse.c index 1ad2ae756d..aff4ffd985 100644 --- a/src/gallium/auxiliary/draw/draw_vf_sse.c +++ b/src/gallium/auxiliary/draw/draw_vf_sse.c @@ -26,17 +26,16 @@   */ -#include "simple_list.h" -  #include "pipe/p_compiler.h" +#include "util/u_simple_list.h"  #include "draw_vf.h"  #if defined(USE_SSE_ASM) -#include "x86/rtasm/x86sse.h" -#include "x86/common_x86_asm.h" +#include "rtasm/rtasm_cpu.h" +#include "rtasm/rtasm_x86sse.h"  #define X    0 @@ -576,7 +575,7 @@ void draw_vf_generate_sse_emit( struct draw_vertex_fetch *vf )  {     struct x86_program p;    -   if (!cpu_has_xmm) { +   if (!rtasm_cpu_has_sse()) {        vf->codegen_emit = NULL;        return;     } @@ -586,7 +585,7 @@ void draw_vf_generate_sse_emit( struct draw_vertex_fetch *vf )     p.vf = vf;     p.inputs_safe = 0;		/* for now */     p.outputs_safe = 1;		/* for now */ -   p.have_sse2 = cpu_has_xmm2; +   p.have_sse2 = rtasm_cpu_has_sse2();     p.identity = x86_make_reg(file_XMM, 6);     p.chan0 = x86_make_reg(file_XMM, 7); diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c index 44022b6e07..0fd557d667 100644 --- a/src/gallium/auxiliary/draw/draw_vs_llvm.c +++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c @@ -40,7 +40,7 @@  #ifdef MESA_LLVM -#include "llvm/gallivm.h" +#include "gallivm/gallivm.h"  struct draw_llvm_vertex_shader {     struct draw_vertex_shader base; diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c index 27bc66812c..11ef0c503d 100644 --- a/src/gallium/auxiliary/draw/draw_vs_sse.c +++ b/src/gallium/auxiliary/draw/draw_vs_sse.c @@ -41,7 +41,7 @@  #include "draw_private.h"  #include "draw_context.h" -#include "x86/rtasm/x86sse.h" +#include "rtasm/rtasm_x86sse.h"  #include "tgsi/exec/tgsi_sse2.h" diff --git a/src/gallium/auxiliary/draw/draw_wide_prims.c b/src/gallium/auxiliary/draw/draw_wide_prims.c index 655774b155..1f8069bdca 100644 --- a/src/gallium/auxiliary/draw/draw_wide_prims.c +++ b/src/gallium/auxiliary/draw/draw_wide_prims.c @@ -162,70 +162,6 @@ static void wide_line( struct draw_stage *stage,  /** - * Draw a wide line by drawing a quad, using geometry which will - * fullfill GL's antialiased line requirements. - */ -static void wide_line_aa(struct draw_stage *stage, -                         struct prim_header *header) -{ -   const struct wide_stage *wide = wide_stage(stage); -   const float half_width = wide->half_line_width; -   struct prim_header tri; -   struct vertex_header *v[4]; -   float *pos; -   float dx = header->v[1]->data[0][0] - header->v[0]->data[0][0]; -   float dy = header->v[1]->data[0][1] - header->v[0]->data[0][1]; -   const float len = (float) sqrt(dx * dx + dy * dy); -   uint i; - -   dx = dx * half_width / len; -   dy = dy * half_width / len; - -   /* allocate/dup new verts */ -   for (i = 0; i < 4; i++) { -      v[i] = dup_vert(stage, header->v[i/2], i); -   } - -   /* -    * Quad for line from v0 to v1: -    * -    *  1                         3 -    *  +-------------------------+ -    *  |                         | -    *  *v0                     v1* -    *  |                         | -    *  +-------------------------+ -    *  0                         2 -    */ - -   pos = v[0]->data[0]; -   pos[0] += dy; -   pos[1] -= dx; - -   pos = v[1]->data[0]; -   pos[0] -= dy; -   pos[1] += dx; - -   pos = v[2]->data[0]; -   pos[0] += dy; -   pos[1] -= dx; - -   pos = v[3]->data[0]; -   pos[0] -= dy; -   pos[1] += dx; - -   tri.det = header->det;  /* only the sign matters */ - -   tri.v[0] = v[2];  tri.v[1] = v[1];  tri.v[2] = v[0]; -   stage->next->tri( stage->next, &tri ); - -   tri.v[0] = v[3];  tri.v[1] = v[1];  tri.v[2] = v[2]; -   stage->next->tri( stage->next, &tri ); - -} - - -/**   * Set the vertex texcoords for sprite mode.   * Coords may be left untouched or set to a right-side-up or upside-down   * orientation. @@ -379,10 +315,7 @@ static void wide_first_line( struct draw_stage *stage,     wide->half_line_width = 0.5f * draw->rasterizer->line_width;     if (draw->rasterizer->line_width != 1.0) { -      if (draw->rasterizer->line_smooth) -         wide->stage.line = wide_line_aa; -      else -         wide->stage.line = wide_line; +      wide->stage.line = wide_line;     }     else {        wide->stage.line = passthrough_line; diff --git a/src/gallium/auxiliary/llvm/Makefile b/src/gallium/auxiliary/gallivm/Makefile index 39fac6ea4a..39fac6ea4a 100644 --- a/src/gallium/auxiliary/llvm/Makefile +++ b/src/gallium/auxiliary/gallivm/Makefile diff --git a/src/gallium/auxiliary/gallivm/SConscript b/src/gallium/auxiliary/gallivm/SConscript new file mode 100644 index 0000000000..c0aa51b90a --- /dev/null +++ b/src/gallium/auxiliary/gallivm/SConscript @@ -0,0 +1,16 @@ +Import('*') + +gallivm = env.ConvenienceLibrary( +	target = 'gallivm', +	source = [ +        'gallivm.cpp', +        'gallivm_cpu.cpp', +        'instructions.cpp', +        'loweringpass.cpp', +        'tgsitollvm.cpp', +        'storage.cpp', +        'storagesoa.cpp', +        'instructionssoa.cpp', +	]) + +auxiliaries.insert(0, gallivm) diff --git a/src/gallium/auxiliary/llvm/gallivm.cpp b/src/gallium/auxiliary/gallivm/gallivm.cpp index d14bb3b99a..d14bb3b99a 100644 --- a/src/gallium/auxiliary/llvm/gallivm.cpp +++ b/src/gallium/auxiliary/gallivm/gallivm.cpp diff --git a/src/gallium/auxiliary/llvm/gallivm.h b/src/gallium/auxiliary/gallivm/gallivm.h index 92da4bca7f..92da4bca7f 100644 --- a/src/gallium/auxiliary/llvm/gallivm.h +++ b/src/gallium/auxiliary/gallivm/gallivm.h diff --git a/src/gallium/auxiliary/llvm/gallivm_builtins.cpp b/src/gallium/auxiliary/gallivm/gallivm_builtins.cpp index 1796f0a177..1796f0a177 100644 --- a/src/gallium/auxiliary/llvm/gallivm_builtins.cpp +++ b/src/gallium/auxiliary/gallivm/gallivm_builtins.cpp diff --git a/src/gallium/auxiliary/llvm/gallivm_cpu.cpp b/src/gallium/auxiliary/gallivm/gallivm_cpu.cpp index 8f9830d0b1..8f9830d0b1 100644 --- a/src/gallium/auxiliary/llvm/gallivm_cpu.cpp +++ b/src/gallium/auxiliary/gallivm/gallivm_cpu.cpp diff --git a/src/gallium/auxiliary/llvm/gallivm_p.h b/src/gallium/auxiliary/gallivm/gallivm_p.h index cfe7b1901b..cfe7b1901b 100644 --- a/src/gallium/auxiliary/llvm/gallivm_p.h +++ b/src/gallium/auxiliary/gallivm/gallivm_p.h diff --git a/src/gallium/auxiliary/llvm/instructions.cpp b/src/gallium/auxiliary/gallivm/instructions.cpp index 55d39fa5f1..55d39fa5f1 100644 --- a/src/gallium/auxiliary/llvm/instructions.cpp +++ b/src/gallium/auxiliary/gallivm/instructions.cpp diff --git a/src/gallium/auxiliary/llvm/instructions.h b/src/gallium/auxiliary/gallivm/instructions.h index 9ebc17dd8e..9ebc17dd8e 100644 --- a/src/gallium/auxiliary/llvm/instructions.h +++ b/src/gallium/auxiliary/gallivm/instructions.h diff --git a/src/gallium/auxiliary/llvm/instructionssoa.cpp b/src/gallium/auxiliary/gallivm/instructionssoa.cpp index a4d5046637..a4d5046637 100644 --- a/src/gallium/auxiliary/llvm/instructionssoa.cpp +++ b/src/gallium/auxiliary/gallivm/instructionssoa.cpp diff --git a/src/gallium/auxiliary/llvm/instructionssoa.h b/src/gallium/auxiliary/gallivm/instructionssoa.h index 4169dcbb2e..4169dcbb2e 100644 --- a/src/gallium/auxiliary/llvm/instructionssoa.h +++ b/src/gallium/auxiliary/gallivm/instructionssoa.h diff --git a/src/gallium/auxiliary/llvm/llvm_builtins.c b/src/gallium/auxiliary/gallivm/llvm_builtins.c index 4f98d754ba..4f98d754ba 100644 --- a/src/gallium/auxiliary/llvm/llvm_builtins.c +++ b/src/gallium/auxiliary/gallivm/llvm_builtins.c diff --git a/src/gallium/auxiliary/llvm/loweringpass.cpp b/src/gallium/auxiliary/gallivm/loweringpass.cpp index 556dbec366..556dbec366 100644 --- a/src/gallium/auxiliary/llvm/loweringpass.cpp +++ b/src/gallium/auxiliary/gallivm/loweringpass.cpp diff --git a/src/gallium/auxiliary/llvm/loweringpass.h b/src/gallium/auxiliary/gallivm/loweringpass.h index f62dcf6ba7..f62dcf6ba7 100644 --- a/src/gallium/auxiliary/llvm/loweringpass.h +++ b/src/gallium/auxiliary/gallivm/loweringpass.h diff --git a/src/gallium/auxiliary/llvm/storage.cpp b/src/gallium/auxiliary/gallivm/storage.cpp index c4326de8c5..c4326de8c5 100644 --- a/src/gallium/auxiliary/llvm/storage.cpp +++ b/src/gallium/auxiliary/gallivm/storage.cpp diff --git a/src/gallium/auxiliary/llvm/storage.h b/src/gallium/auxiliary/gallivm/storage.h index 8574f7554e..8574f7554e 100644 --- a/src/gallium/auxiliary/llvm/storage.h +++ b/src/gallium/auxiliary/gallivm/storage.h diff --git a/src/gallium/auxiliary/llvm/storagesoa.cpp b/src/gallium/auxiliary/gallivm/storagesoa.cpp index ed0674a96f..ed0674a96f 100644 --- a/src/gallium/auxiliary/llvm/storagesoa.cpp +++ b/src/gallium/auxiliary/gallivm/storagesoa.cpp diff --git a/src/gallium/auxiliary/llvm/storagesoa.h b/src/gallium/auxiliary/gallivm/storagesoa.h index 6443351f27..6443351f27 100644 --- a/src/gallium/auxiliary/llvm/storagesoa.h +++ b/src/gallium/auxiliary/gallivm/storagesoa.h diff --git a/src/gallium/auxiliary/llvm/tgsitollvm.cpp b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp index 2cb4acce32..2cb4acce32 100644 --- a/src/gallium/auxiliary/llvm/tgsitollvm.cpp +++ b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp diff --git a/src/gallium/auxiliary/llvm/tgsitollvm.h b/src/gallium/auxiliary/gallivm/tgsitollvm.h index 7ada04d629..7ada04d629 100644 --- a/src/gallium/auxiliary/llvm/tgsitollvm.h +++ b/src/gallium/auxiliary/gallivm/tgsitollvm.h diff --git a/src/gallium/auxiliary/pipebuffer/Makefile b/src/gallium/auxiliary/pipebuffer/Makefile index 588629e870..a9fa518c67 100644 --- a/src/gallium/auxiliary/pipebuffer/Makefile +++ b/src/gallium/auxiliary/pipebuffer/Makefile @@ -1,10 +1,9 @@ -  TOP = ../../../..  include $(TOP)/configs/current  LIBNAME = pipebuffer -DRIVER_SOURCES = \ +C_SOURCES = \  	pb_buffer_fenced.c \  	pb_buffer_malloc.c \  	pb_bufmgr_fenced.c \ @@ -12,11 +11,6 @@ DRIVER_SOURCES = \  	pb_bufmgr_pool.c \  	pb_winsys.c -C_SOURCES = \ -	$(DRIVER_SOURCES) - -ASM_SOURCES =  -  include ../../Makefile.template  symlinks: diff --git a/src/gallium/auxiliary/pipebuffer/SConscript b/src/gallium/auxiliary/pipebuffer/SConscript new file mode 100644 index 0000000000..3d41fd84a6 --- /dev/null +++ b/src/gallium/auxiliary/pipebuffer/SConscript @@ -0,0 +1,14 @@ +Import('*') + +pipebuffer = env.ConvenienceLibrary( +	target = 'pipebuffer', +	source = [ +		'pb_buffer_fenced.c', +		'pb_buffer_malloc.c', +		'pb_bufmgr_fenced.c', +		'pb_bufmgr_mm.c', +		'pb_bufmgr_pool.c', +		'pb_winsys.c', +	]) + +auxiliaries.insert(0, pipebuffer) diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c index f4fc3f6d71..e2ee72ed1f 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c @@ -34,13 +34,12 @@   */ -#include "linked_list.h" - -#include "p_compiler.h" -#include "p_debug.h" -#include "p_winsys.h" -#include "p_thread.h" -#include "p_util.h" +#include "pipe/p_compiler.h" +#include "pipe/p_debug.h" +#include "pipe/p_winsys.h" +#include "pipe/p_thread.h" +#include "pipe/p_util.h" +#include "util/u_double_list.h"  #include "pb_buffer.h"  #include "pb_buffer_fenced.h" diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c index c535d3276c..bffca5b244 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c @@ -34,8 +34,8 @@   */ -#include "p_debug.h" -#include "p_util.h" +#include "pipe/p_debug.h" +#include "pipe/p_util.h"  #include "pb_buffer.h"  #include "pb_buffer_fenced.h" diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c index 8b1b51c0e2..ff4fd123f3 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c @@ -1,7 +1,6 @@  /**************************************************************************   *   * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. - * Copyright 1999 Wittawat Yamwong   * All Rights Reserved.   *   * Permission is hereby granted, free of charge, to any person obtaining a @@ -34,12 +33,12 @@   */ -#include "linked_list.h" - -#include "p_defines.h" -#include "p_debug.h" -#include "p_thread.h" -#include "p_util.h" +#include "pipe/p_defines.h" +#include "pipe/p_debug.h" +#include "pipe/p_thread.h" +#include "pipe/p_util.h" +#include "util/u_double_list.h" +#include "util/u_mm.h"  #include "pb_buffer.h"  #include "pb_bufmgr.h" @@ -50,306 +49,6 @@  #define SUPER(__derived) (&(__derived)->base) -struct mem_block  -{ -   struct mem_block *next, *prev; -   struct mem_block *next_free, *prev_free; -   struct mem_block *heap; -   int ofs, size; -   unsigned int free:1; -   unsigned int reserved:1; -}; - - -#ifdef DEBUG -/** - * For debugging purposes. - */ -static void -mmDumpMemInfo(const struct mem_block *heap) -{ -   debug_printf("Memory heap %p:\n", (void *)heap); -   if (heap == 0) { -      debug_printf("  heap == 0\n"); -   } else { -      const struct mem_block *p; - -      for(p = heap->next; p != heap; p = p->next) { -	 debug_printf("  Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, -		 p->free ? 'F':'.', -		 p->reserved ? 'R':'.'); -      } - -      debug_printf("\nFree list:\n"); - -      for(p = heap->next_free; p != heap; p = p->next_free) { -	 debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, -		 p->free ? 'F':'.', -		 p->reserved ? 'R':'.'); -      } - -   } -   debug_printf("End of memory blocks\n"); -} -#endif - - -/**  - * input: total size in bytes - * return: a heap pointer if OK, NULL if error - */ -static struct mem_block * -mmInit(int ofs, int size) -{ -   struct mem_block *heap, *block; -   -   if (size <= 0)  -      return NULL; - -   heap = CALLOC_STRUCT(mem_block); -   if (!heap)  -      return NULL; -    -   block = CALLOC_STRUCT(mem_block); -   if (!block) { -      FREE(heap); -      return NULL; -   } - -   heap->next = block; -   heap->prev = block; -   heap->next_free = block; -   heap->prev_free = block; - -   block->heap = heap; -   block->next = heap; -   block->prev = heap; -   block->next_free = heap; -   block->prev_free = heap; - -   block->ofs = ofs; -   block->size = size; -   block->free = 1; - -   return heap; -} - - -static struct mem_block * -SliceBlock(struct mem_block *p,  -           int startofs, int size,  -           int reserved, int alignment) -{ -   struct mem_block *newblock; - -   /* break left  [p, newblock, p->next], then p = newblock */ -   if (startofs > p->ofs) { -      newblock = CALLOC_STRUCT(mem_block); -      if (!newblock) -	 return NULL; -      newblock->ofs = startofs; -      newblock->size = p->size - (startofs - p->ofs); -      newblock->free = 1; -      newblock->heap = p->heap; - -      newblock->next = p->next; -      newblock->prev = p; -      p->next->prev = newblock; -      p->next = newblock; - -      newblock->next_free = p->next_free; -      newblock->prev_free = p; -      p->next_free->prev_free = newblock; -      p->next_free = newblock; - -      p->size -= newblock->size; -      p = newblock; -   } - -   /* break right, also [p, newblock, p->next] */ -   if (size < p->size) { -      newblock = CALLOC_STRUCT(mem_block); -      if (!newblock) -	 return NULL; -      newblock->ofs = startofs + size; -      newblock->size = p->size - size; -      newblock->free = 1; -      newblock->heap = p->heap; - -      newblock->next = p->next; -      newblock->prev = p; -      p->next->prev = newblock; -      p->next = newblock; - -      newblock->next_free = p->next_free; -      newblock->prev_free = p; -      p->next_free->prev_free = newblock; -      p->next_free = newblock; -	  -      p->size = size; -   } - -   /* p = middle block */ -   p->free = 0; - -   /* Remove p from the free list:  -    */ -   p->next_free->prev_free = p->prev_free; -   p->prev_free->next_free = p->next_free; - -   p->next_free = 0; -   p->prev_free = 0; - -   p->reserved = reserved; -   return p; -} - - -/** - * Allocate 'size' bytes with 2^align2 bytes alignment, - * restrict the search to free memory after 'startSearch' - * depth and back buffers should be in different 4mb banks - * to get better page hits if possible - * input:	size = size of block - *       	align2 = 2^align2 bytes alignment - *		startSearch = linear offset from start of heap to begin search - * return: pointer to the allocated block, 0 if error - */ -static struct mem_block * -mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch) -{ -   struct mem_block *p; -   const int mask = (1 << align2)-1; -   int startofs = 0; -   int endofs; - -   if (!heap || align2 < 0 || size <= 0) -      return NULL; - -   for (p = heap->next_free; p != heap; p = p->next_free) { -      assert(p->free); - -      startofs = (p->ofs + mask) & ~mask; -      if ( startofs < startSearch ) { -	 startofs = startSearch; -      } -      endofs = startofs+size; -      if (endofs <= (p->ofs+p->size)) -	 break; -   } - -   if (p == heap)  -      return NULL; - -   assert(p->free); -   p = SliceBlock(p,startofs,size,0,mask+1); - -   return p; -} - - -#if 0 -/** - * Free block starts at offset - * input: pointer to a heap, start offset - * return: pointer to a block - */ -static struct mem_block * -mmFindBlock(struct mem_block *heap, int start) -{ -   struct mem_block *p; - -   for (p = heap->next; p != heap; p = p->next) { -      if (p->ofs == start)  -	 return p; -   } - -   return NULL; -} -#endif - - -static INLINE int -Join2Blocks(struct mem_block *p) -{ -   /* XXX there should be some assertions here */ - -   /* NOTE: heap->free == 0 */ - -   if (p->free && p->next->free) { -      struct mem_block *q = p->next; - -      assert(p->ofs + p->size == q->ofs); -      p->size += q->size; - -      p->next = q->next; -      q->next->prev = p; - -      q->next_free->prev_free = q->prev_free;  -      q->prev_free->next_free = q->next_free; -      -      FREE(q); -      return 1; -   } -   return 0; -} - - -/** - * Free block starts at offset - * input: pointer to a block - * return: 0 if OK, -1 if error - */ -static int -mmFreeMem(struct mem_block *b) -{ -   if (!b) -      return 0; - -   if (b->free) { -      debug_printf("block already free\n"); -      return -1; -   } -   if (b->reserved) { -      debug_printf("block is reserved\n"); -      return -1; -   } - -   b->free = 1; -   b->next_free = b->heap->next_free; -   b->prev_free = b->heap; -   b->next_free->prev_free = b; -   b->prev_free->next_free = b; - -   Join2Blocks(b); -   if (b->prev != b->heap) -      Join2Blocks(b->prev); - -   return 0; -} - - -/** - * destroy MM - */ -static void -mmDestroy(struct mem_block *heap) -{ -   struct mem_block *p; - -   if (!heap) -      return; - -   for (p = heap->next; p != heap; ) { -      struct mem_block *next = p->next; -      FREE(p); -      p = next; -   } - -   FREE(heap); -} - -  struct mm_pb_manager  {     struct pb_manager base; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c index 04477a865a..528e9528f6 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c @@ -35,13 +35,12 @@   */ -#include "linked_list.h" - -#include "p_compiler.h" -#include "p_debug.h" -#include "p_thread.h" -#include "p_defines.h" -#include "p_util.h" +#include "pipe/p_compiler.h" +#include "pipe/p_debug.h" +#include "pipe/p_thread.h" +#include "pipe/p_defines.h" +#include "pipe/p_util.h" +#include "util/u_double_list.h"  #include "pb_buffer.h"  #include "pb_bufmgr.h" diff --git a/src/gallium/auxiliary/rtasm/Makefile b/src/gallium/auxiliary/rtasm/Makefile new file mode 100644 index 0000000000..39b8a4dbd7 --- /dev/null +++ b/src/gallium/auxiliary/rtasm/Makefile @@ -0,0 +1,15 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = rtasm + +C_SOURCES = \ +	rtasm_cpu.c \ +	rtasm_execmem.c \ +	rtasm_x86sse.c \ +	rtasm_ppc_spe.c + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/auxiliary/rtasm/SConscript b/src/gallium/auxiliary/rtasm/SConscript new file mode 100644 index 0000000000..8ea25922aa --- /dev/null +++ b/src/gallium/auxiliary/rtasm/SConscript @@ -0,0 +1,12 @@ +Import('*') + +rtasm = env.ConvenienceLibrary( +	target = 'rtasm', +	source = [ +		'rtasm_cpu.c', +		'rtasm_execmem.c', +		'rtasm_x86sse.c', +		'rtasm_ppc_spe.c', +	]) + +auxiliaries.insert(0, rtasm) diff --git a/src/gallium/drivers/cell/ppu/cell_state_sampler.c b/src/gallium/auxiliary/rtasm/rtasm_cpu.c index a33421a4ad..eb3359750b 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_sampler.c +++ b/src/gallium/auxiliary/rtasm/rtasm_cpu.c @@ -1,6 +1,6 @@  /************************************************************************** - *  - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.   * All Rights Reserved.   *   * Permission is hereby granted, free of charge, to any person obtaining a @@ -10,11 +10,11 @@   * distribute, sub license, and/or sell copies of the Software, and to   * permit persons to whom the Software is furnished to do so, subject to   * the following conditions: - *  + *   * The above copyright notice and this permission notice (including the   * next paragraph) shall be included in all copies or substantial portions   * of the Software. - *  + *   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS   * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. @@ -22,63 +22,29 @@   * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE   * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - *  + *   **************************************************************************/ -/* Authors: - *  Brian Paul - */ - -#include "pipe/p_util.h" -#include "draw/draw_context.h" -#include "cell_context.h" -#include "cell_state.h" -#include "cell_texture.h" - - -void * -cell_create_sampler_state(struct pipe_context *pipe, -                          const struct pipe_sampler_state *sampler) -{ -   return mem_dup(sampler, sizeof(*sampler)); -} - -void -cell_bind_sampler_state(struct pipe_context *pipe, -                            unsigned unit, void *sampler) -{ -   struct cell_context *cell = cell_context(pipe); - -   draw_flush(cell->draw); -   assert(unit < PIPE_MAX_SAMPLERS); -   cell->sampler[unit] = (struct pipe_sampler_state *)sampler; +#include "rtasm_cpu.h" -   cell->dirty |= CELL_NEW_SAMPLER; -} - -void -cell_delete_sampler_state(struct pipe_context *pipe, -                              void *sampler) +int rtasm_cpu_has_sse(void)  { -   FREE( sampler ); +   /* FIXME: actually detect this at run-time */ +#if defined(__i386__) || defined(__386__) +   return 1; +#else +   return 0; +#endif  } - - -void -cell_set_sampler_texture(struct pipe_context *pipe, -                         unsigned sampler, -                         struct pipe_texture *texture) +int rtasm_cpu_has_sse2(void)   { -   struct cell_context *cell = cell_context(pipe); - -   draw_flush(cell->draw); - -   cell->texture[sampler] = texture; - -   cell_update_texture_mapping(cell); - -   cell->dirty |= CELL_NEW_TEXTURE; +   /* FIXME: actually detect this at run-time */ +#if defined(__i386__) || defined(__386__) +   return 1; +#else +   return 0; +#endif  } diff --git a/src/gallium/auxiliary/rtasm/rtasm_cpu.h b/src/gallium/auxiliary/rtasm/rtasm_cpu.h new file mode 100644 index 0000000000..ebc71634fd --- /dev/null +++ b/src/gallium/auxiliary/rtasm/rtasm_cpu.h @@ -0,0 +1,42 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * Runtime detection of CPU capabilities. + */ + +#ifndef _RTASM_CPU_H_ +#define _RTASM_CPU_H_ + + +int rtasm_cpu_has_sse(void); + +int rtasm_cpu_has_sse2(void); + + +#endif /* _RTASM_CPU_H_ */ diff --git a/src/gallium/auxiliary/rtasm/rtasm_execmem.c b/src/gallium/auxiliary/rtasm/rtasm_execmem.c new file mode 100644 index 0000000000..300c1c2d9d --- /dev/null +++ b/src/gallium/auxiliary/rtasm/rtasm_execmem.c @@ -0,0 +1,135 @@ +/************************************************************************** + * + * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/** + * \file exemem.c + * Functions for allocating executable memory. + * + * \author Keith Whitwell + */ + + +#include "pipe/p_compiler.h" +#include "pipe/p_debug.h" +#include "pipe/p_thread.h" +#include "pipe/p_util.h" + +#include "rtasm_execmem.h" + + +#if defined(__linux__) + +/* + * Allocate a large block of memory which can hold code then dole it out + * in pieces by means of the generic memory manager code. +*/ + +#include <unistd.h> +#include <sys/mman.h> +#include "util/u_mm.h" + +#define EXEC_HEAP_SIZE (10*1024*1024) + +_glthread_DECLARE_STATIC_MUTEX(exec_mutex); + +static struct mem_block *exec_heap = NULL; +static unsigned char *exec_mem = NULL; + + +static void +init_heap(void) +{ +   if (!exec_heap) +      exec_heap = mmInit( 0, EXEC_HEAP_SIZE ); +    +   if (!exec_mem) +      exec_mem = (unsigned char *) mmap(0, EXEC_HEAP_SIZE,  +					PROT_EXEC | PROT_READ | PROT_WRITE,  +					MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +} + + +void * +rtasm_exec_malloc(size_t size) +{ +   struct mem_block *block = NULL; +   void *addr = NULL; + +   _glthread_LOCK_MUTEX(exec_mutex); + +   init_heap(); + +   if (exec_heap) { +      size = (size + 31) & ~31; +      block = mmAllocMem( exec_heap, size, 32, 0 ); +   } + +   if (block) +      addr = exec_mem + block->ofs; +   else  +      debug_printf("rtasm_exec_malloc failed\n"); +    +   _glthread_UNLOCK_MUTEX(exec_mutex); +    +   return addr; +} + +  +void  +rtasm_exec_free(void *addr) +{ +   _glthread_LOCK_MUTEX(exec_mutex); + +   if (exec_heap) { +      struct mem_block *block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem); +    +      if (block) +	 mmFreeMem(block); +   } + +   _glthread_UNLOCK_MUTEX(exec_mutex); +} + + +#else + +/* + * Just use regular memory. + */ + +void * +rtasm_exec_malloc(size_t size) +{ +   return MALLOC( size ); +} + +  +void  +rtasm_exec_free(void *addr) +{ +   FREE(addr); +} + + +#endif diff --git a/src/gallium/auxiliary/rtasm/rtasm_execmem.h b/src/gallium/auxiliary/rtasm/rtasm_execmem.h new file mode 100644 index 0000000000..155c6d34e0 --- /dev/null +++ b/src/gallium/auxiliary/rtasm/rtasm_execmem.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * \file exemem.c + * Functions for allocating executable memory. + * + * \author Keith Whitwell + */ + +#ifndef _RTASM_EXECMEM_H_ +#define _RTASM_EXECMEM_H_ + +#include "pipe/p_compiler.h" + + +extern void * +rtasm_exec_malloc( size_t size ); + + +extern void  +rtasm_exec_free( void *addr ); + + +#endif diff --git a/src/mesa/ppc/rtasm/spe_asm.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 1037637250..95a2d6fcbb 100644 --- a/src/mesa/ppc/rtasm/spe_asm.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -23,16 +23,17 @@   */  /** - * \file spe_asm.c + * \file   * Real-time assembly generation interface for Cell B.E. SPEs.   *   * \author Ian Romanick <idr@us.ibm.com>   */ -#ifdef GALLIUM_CELL -#include <inttypes.h> -#include <imports.h> -#include "spe_asm.h" +#include "pipe/p_compiler.h" +#include "pipe/p_util.h" +#include "rtasm_ppc_spe.h" + +#ifdef GALLIUM_CELL  /**   * SPE instruction types   * @@ -296,21 +297,21 @@ void _name (struct spe_function *p, int imm) \      emit_RI16(p, _op, 0, imm); \  } -#include "spe_asm.h" +#include "rtasm_ppc_spe.h"  /*   */  void spe_init_func(struct spe_function *p, unsigned code_size)  { -    p->store = _mesa_align_malloc(code_size, 16); +    p->store = align_malloc(code_size, 16);      p->csr = p->store;  }  void spe_release_func(struct spe_function *p)  { -    _mesa_align_free(p->store); +    align_free(p->store);      p->store = NULL;      p->csr = NULL;  } diff --git a/src/mesa/ppc/rtasm/spe_asm.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index 6d69ae655d..10ce44b3a0 100644 --- a/src/mesa/ppc/rtasm/spe_asm.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -23,14 +23,14 @@   */  /** - * \file spe_asm.h + * \file   * Real-time assembly generation interface for Cell B.E. SPEs.   *   * \author Ian Romanick <idr@us.ibm.com>   */ -#ifndef SPE_ASM_H -#define SPE_ASM_H +#ifndef RTASM_PPC_SPE_H +#define RTASM_PPC_SPE_H  struct spe_function {      /** @@ -44,7 +44,7 @@ struct spe_function {  extern void spe_init_func(struct spe_function *p, unsigned code_size);  extern void spe_release_func(struct spe_function *p); -#endif /* SPE_ASM_H */ +#endif /* RTASM_PPC_SPE_H */  #ifndef EMIT_  #define EMIT_(name, _op) \ diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c new file mode 100644 index 0000000000..dcbf76f600 --- /dev/null +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c @@ -0,0 +1,1219 @@ +/************************************************************************** + * + * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#if defined(__i386__) || defined(__386__) || defined(i386) + +#include "pipe/p_compiler.h" +#include "pipe/p_debug.h" + +#include "rtasm_execmem.h" +#include "rtasm_x86sse.h" + +#define DISASSEM 0 +#define X86_TWOB 0x0f + +static unsigned char *cptr( void (*label)() ) +{ +   return (unsigned char *)(unsigned long)label; +} + + +static void do_realloc( struct x86_function *p ) +{ +   if (p->size == 0) { +      p->size = 1024; +      p->store = rtasm_exec_malloc(p->size); +      p->csr = p->store; +   } +   else { +      unsigned used = p->csr - p->store; +      unsigned char *tmp = p->store; +      p->size *= 2; +      p->store = rtasm_exec_malloc(p->size); +      memcpy(p->store, tmp, used); +      p->csr = p->store + used; +      rtasm_exec_free(tmp); +   } +} + +/* Emit bytes to the instruction stream: + */ +static unsigned char *reserve( struct x86_function *p, int bytes ) +{ +   if (p->csr + bytes - p->store > p->size) +      do_realloc(p); + +   { +      unsigned char *csr = p->csr; +      p->csr += bytes; +      return csr; +   } +} + + + +static void emit_1b( struct x86_function *p, char b0 ) +{ +   char *csr = (char *)reserve(p, 1); +   *csr = b0; +} + +static void emit_1i( struct x86_function *p, int i0 ) +{ +   int *icsr = (int *)reserve(p, sizeof(i0)); +   *icsr = i0; +} + +static void emit_1ub( struct x86_function *p, unsigned char b0 ) +{ +   unsigned char *csr = reserve(p, 1); +   *csr++ = b0; +} + +static void emit_2ub( struct x86_function *p, unsigned char b0, unsigned char b1 ) +{ +   unsigned char *csr = reserve(p, 2); +   *csr++ = b0; +   *csr++ = b1; +} + +static void emit_3ub( struct x86_function *p, unsigned char b0, unsigned char b1, unsigned char b2 ) +{ +   unsigned char *csr = reserve(p, 3); +   *csr++ = b0; +   *csr++ = b1; +   *csr++ = b2; +} + + +/* Build a modRM byte + possible displacement.  No treatment of SIB + * indexing.  BZZT - no way to encode an absolute address. + */ +static void emit_modrm( struct x86_function *p,  +			struct x86_reg reg,  +			struct x86_reg regmem ) +{ +   unsigned char val = 0; +    +   assert(reg.mod == mod_REG); +    +   val |= regmem.mod << 6;     	/* mod field */ +   val |= reg.idx << 3;		/* reg field */ +   val |= regmem.idx;		/* r/m field */ +    +   emit_1ub(p, val); + +   /* Oh-oh we've stumbled into the SIB thing. +    */ +   if (regmem.file == file_REG32 && +       regmem.idx == reg_SP) { +      emit_1ub(p, 0x24);		/* simplistic! */ +   } + +   switch (regmem.mod) { +   case mod_REG: +   case mod_INDIRECT: +      break; +   case mod_DISP8: +      emit_1b(p, regmem.disp); +      break; +   case mod_DISP32: +      emit_1i(p, regmem.disp); +      break; +   default: +      assert(0); +      break; +   } +} + + +static void emit_modrm_noreg( struct x86_function *p, +			      unsigned op, +			      struct x86_reg regmem ) +{ +   struct x86_reg dummy = x86_make_reg(file_REG32, op); +   emit_modrm(p, dummy, regmem); +} + +/* Many x86 instructions have two opcodes to cope with the situations + * where the destination is a register or memory reference + * respectively.  This function selects the correct opcode based on + * the arguments presented. + */ +static void emit_op_modrm( struct x86_function *p, +			   unsigned char op_dst_is_reg,  +			   unsigned char op_dst_is_mem, +			   struct x86_reg dst, +			   struct x86_reg src ) +{   +   switch (dst.mod) { +   case mod_REG: +      emit_1ub(p, op_dst_is_reg); +      emit_modrm(p, dst, src); +      break; +   case mod_INDIRECT: +   case mod_DISP32: +   case mod_DISP8: +      assert(src.mod == mod_REG); +      emit_1ub(p, op_dst_is_mem); +      emit_modrm(p, src, dst); +      break; +   default: +      assert(0); +      break; +   } +} + + + + + + + +/* Create and manipulate registers and regmem values: + */ +struct x86_reg x86_make_reg( enum x86_reg_file file, +			     enum x86_reg_name idx ) +{ +   struct x86_reg reg; + +   reg.file = file; +   reg.idx = idx; +   reg.mod = mod_REG; +   reg.disp = 0; + +   return reg; +} + +struct x86_reg x86_make_disp( struct x86_reg reg, +			      int disp ) +{ +   assert(reg.file == file_REG32); + +   if (reg.mod == mod_REG) +      reg.disp = disp; +   else +      reg.disp += disp; + +   if (reg.disp == 0) +      reg.mod = mod_INDIRECT; +   else if (reg.disp <= 127 && reg.disp >= -128) +      reg.mod = mod_DISP8; +   else +      reg.mod = mod_DISP32; + +   return reg; +} + +struct x86_reg x86_deref( struct x86_reg reg ) +{ +   return x86_make_disp(reg, 0); +} + +struct x86_reg x86_get_base_reg( struct x86_reg reg ) +{ +   return x86_make_reg( reg.file, reg.idx ); +} + +unsigned char *x86_get_label( struct x86_function *p ) +{ +   return p->csr; +} + + + +/*********************************************************************** + * x86 instructions + */ + + +void x86_jcc( struct x86_function *p, +	      enum x86_cc cc, +	      unsigned char *label ) +{ +   int offset = label - (x86_get_label(p) + 2); +    +   if (offset <= 127 && offset >= -128) { +      emit_1ub(p, 0x70 + cc); +      emit_1b(p, (char) offset); +   } +   else { +      offset = label - (x86_get_label(p) + 6); +      emit_2ub(p, 0x0f, 0x80 + cc); +      emit_1i(p, offset); +   } +} + +/* Always use a 32bit offset for forward jumps: + */ +unsigned char *x86_jcc_forward( struct x86_function *p, +			  enum x86_cc cc ) +{ +   emit_2ub(p, 0x0f, 0x80 + cc); +   emit_1i(p, 0); +   return x86_get_label(p); +} + +unsigned char *x86_jmp_forward( struct x86_function *p) +{ +   emit_1ub(p, 0xe9); +   emit_1i(p, 0); +   return x86_get_label(p); +} + +unsigned char *x86_call_forward( struct x86_function *p) +{ +   emit_1ub(p, 0xe8); +   emit_1i(p, 0); +   return x86_get_label(p); +} + +/* Fixup offset from forward jump: + */ +void x86_fixup_fwd_jump( struct x86_function *p, +			 unsigned char *fixup ) +{ +   *(int *)(fixup - 4) = x86_get_label(p) - fixup; +} + +void x86_jmp( struct x86_function *p, unsigned char *label) +{ +   emit_1ub(p, 0xe9); +   emit_1i(p, label - x86_get_label(p) - 4); +} + +#if 0 +/* This doesn't work once we start reallocating & copying the + * generated code on buffer fills, because the call is relative to the + * current pc. + */ +void x86_call( struct x86_function *p, void (*label)()) +{ +   emit_1ub(p, 0xe8); +   emit_1i(p, cptr(label) - x86_get_label(p) - 4); +} +#else +void x86_call( struct x86_function *p, struct x86_reg reg) +{ +   emit_1ub(p, 0xff); +   emit_modrm(p, reg, reg); +} +#endif + + +/* michal: + * Temporary. As I need immediate operands, and dont want to mess with the codegen, + * I load the immediate into general purpose register and use it. + */ +void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ) +{ +   assert(dst.mod == mod_REG); +   emit_1ub(p, 0xb8 + dst.idx); +   emit_1i(p, imm); +} + +void x86_push( struct x86_function *p, +	       struct x86_reg reg ) +{ +   assert(reg.mod == mod_REG); +   emit_1ub(p, 0x50 + reg.idx); +   p->stack_offset += 4; +} + +void x86_pop( struct x86_function *p, +	      struct x86_reg reg ) +{ +   assert(reg.mod == mod_REG); +   emit_1ub(p, 0x58 + reg.idx); +   p->stack_offset -= 4; +} + +void x86_inc( struct x86_function *p, +	      struct x86_reg reg ) +{ +   assert(reg.mod == mod_REG); +   emit_1ub(p, 0x40 + reg.idx); +} + +void x86_dec( struct x86_function *p, +	      struct x86_reg reg ) +{ +   assert(reg.mod == mod_REG); +   emit_1ub(p, 0x48 + reg.idx); +} + +void x86_ret( struct x86_function *p ) +{ +   emit_1ub(p, 0xc3); +} + +void x86_sahf( struct x86_function *p ) +{ +   emit_1ub(p, 0x9e); +} + +void x86_mov( struct x86_function *p, +	      struct x86_reg dst, +	      struct x86_reg src ) +{ +   emit_op_modrm( p, 0x8b, 0x89, dst, src ); +} + +void x86_xor( struct x86_function *p, +	      struct x86_reg dst, +	      struct x86_reg src ) +{ +   emit_op_modrm( p, 0x33, 0x31, dst, src ); +} + +void x86_cmp( struct x86_function *p, +	      struct x86_reg dst, +	      struct x86_reg src ) +{ +   emit_op_modrm( p, 0x3b, 0x39, dst, src ); +} + +void x86_lea( struct x86_function *p, +	      struct x86_reg dst, +	      struct x86_reg src ) +{ +   emit_1ub(p, 0x8d); +   emit_modrm( p, dst, src ); +} + +void x86_test( struct x86_function *p, +	       struct x86_reg dst, +	       struct x86_reg src ) +{ +   emit_1ub(p, 0x85); +   emit_modrm( p, dst, src ); +} + +void x86_add( struct x86_function *p, +	       struct x86_reg dst, +	       struct x86_reg src ) +{ +   emit_op_modrm(p, 0x03, 0x01, dst, src ); +} + +void x86_mul( struct x86_function *p, +	       struct x86_reg src ) +{ +   assert (src.file == file_REG32 && src.mod == mod_REG); +   emit_op_modrm(p, 0xf7, 0, x86_make_reg (file_REG32, reg_SP), src ); +} + +void x86_sub( struct x86_function *p, +	       struct x86_reg dst, +	       struct x86_reg src ) +{ +   emit_op_modrm(p, 0x2b, 0x29, dst, src ); +} + +void x86_or( struct x86_function *p, +             struct x86_reg dst, +             struct x86_reg src ) +{ +   emit_op_modrm( p, 0x0b, 0x09, dst, src ); +} + +void x86_and( struct x86_function *p, +              struct x86_reg dst, +              struct x86_reg src ) +{ +   emit_op_modrm( p, 0x23, 0x21, dst, src ); +} + + + +/*********************************************************************** + * SSE instructions + */ + + +void sse_movss( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_2ub(p, 0xF3, X86_TWOB); +   emit_op_modrm( p, 0x10, 0x11, dst, src ); +} + +void sse_movaps( struct x86_function *p, +		 struct x86_reg dst, +		 struct x86_reg src ) +{ +   emit_1ub(p, X86_TWOB); +   emit_op_modrm( p, 0x28, 0x29, dst, src ); +} + +void sse_movups( struct x86_function *p, +		 struct x86_reg dst, +		 struct x86_reg src ) +{ +   emit_1ub(p, X86_TWOB); +   emit_op_modrm( p, 0x10, 0x11, dst, src ); +} + +void sse_movhps( struct x86_function *p, +		 struct x86_reg dst, +		 struct x86_reg src ) +{ +   assert(dst.mod != mod_REG || src.mod != mod_REG); +   emit_1ub(p, X86_TWOB); +   emit_op_modrm( p, 0x16, 0x17, dst, src ); /* cf movlhps */ +} + +void sse_movlps( struct x86_function *p, +		 struct x86_reg dst, +		 struct x86_reg src ) +{ +   assert(dst.mod != mod_REG || src.mod != mod_REG); +   emit_1ub(p, X86_TWOB); +   emit_op_modrm( p, 0x12, 0x13, dst, src ); /* cf movhlps */ +} + +void sse_maxps( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x5F); +   emit_modrm( p, dst, src ); +} + +void sse_maxss( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_3ub(p, 0xF3, X86_TWOB, 0x5F); +   emit_modrm( p, dst, src ); +} + +void sse_divss( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_3ub(p, 0xF3, X86_TWOB, 0x5E); +   emit_modrm( p, dst, src ); +} + +void sse_minps( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x5D); +   emit_modrm( p, dst, src ); +} + +void sse_subps( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x5C); +   emit_modrm( p, dst, src ); +} + +void sse_mulps( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x59); +   emit_modrm( p, dst, src ); +} + +void sse_mulss( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_3ub(p, 0xF3, X86_TWOB, 0x59); +   emit_modrm( p, dst, src ); +} + +void sse_addps( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x58); +   emit_modrm( p, dst, src ); +} + +void sse_addss( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_3ub(p, 0xF3, X86_TWOB, 0x58); +   emit_modrm( p, dst, src ); +} + +void sse_andnps( struct x86_function *p, +                 struct x86_reg dst, +                 struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x55); +   emit_modrm( p, dst, src ); +} + +void sse_andps( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x54); +   emit_modrm( p, dst, src ); +} + +void sse_rsqrtps( struct x86_function *p, +                  struct x86_reg dst, +                  struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x52); +   emit_modrm( p, dst, src ); +} + +void sse_rsqrtss( struct x86_function *p, +		  struct x86_reg dst, +		  struct x86_reg src ) +{ +   emit_3ub(p, 0xF3, X86_TWOB, 0x52); +   emit_modrm( p, dst, src ); + +} + +void sse_movhlps( struct x86_function *p, +		  struct x86_reg dst, +		  struct x86_reg src ) +{ +   assert(dst.mod == mod_REG && src.mod == mod_REG); +   emit_2ub(p, X86_TWOB, 0x12); +   emit_modrm( p, dst, src ); +} + +void sse_movlhps( struct x86_function *p, +		  struct x86_reg dst, +		  struct x86_reg src ) +{ +   assert(dst.mod == mod_REG && src.mod == mod_REG); +   emit_2ub(p, X86_TWOB, 0x16); +   emit_modrm( p, dst, src ); +} + +void sse_orps( struct x86_function *p, +               struct x86_reg dst, +               struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x56); +   emit_modrm( p, dst, src ); +} + +void sse_xorps( struct x86_function *p, +                struct x86_reg dst, +                struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x57); +   emit_modrm( p, dst, src ); +} + +void sse_cvtps2pi( struct x86_function *p, +		   struct x86_reg dst, +		   struct x86_reg src ) +{ +   assert(dst.file == file_MMX &&  +	  (src.file == file_XMM || src.mod != mod_REG)); + +   p->need_emms = 1; + +   emit_2ub(p, X86_TWOB, 0x2d); +   emit_modrm( p, dst, src ); +} + + +/* Shufps can also be used to implement a reduced swizzle when dest == + * arg0. + */ +void sse_shufps( struct x86_function *p, +		 struct x86_reg dest, +		 struct x86_reg arg0, +		 unsigned char shuf)  +{ +   emit_2ub(p, X86_TWOB, 0xC6); +   emit_modrm(p, dest, arg0); +   emit_1ub(p, shuf);  +} + +void sse_cmpps( struct x86_function *p, +		struct x86_reg dest, +		struct x86_reg arg0, +		unsigned char cc)  +{ +   emit_2ub(p, X86_TWOB, 0xC2); +   emit_modrm(p, dest, arg0); +   emit_1ub(p, cc);  +} + +void sse_pmovmskb( struct x86_function *p, +                   struct x86_reg dest, +                   struct x86_reg src) +{ +    emit_3ub(p, 0x66, X86_TWOB, 0xD7); +    emit_modrm(p, dest, src); +} + +/*********************************************************************** + * SSE2 instructions + */ + +/** + * Perform a reduced swizzle: + */ +void sse2_pshufd( struct x86_function *p, +		  struct x86_reg dest, +		  struct x86_reg arg0, +		  unsigned char shuf)  +{ +   emit_3ub(p, 0x66, X86_TWOB, 0x70); +   emit_modrm(p, dest, arg0); +   emit_1ub(p, shuf);  +} + +void sse2_cvttps2dq( struct x86_function *p, +                     struct x86_reg dst, +                     struct x86_reg src ) +{ +   emit_3ub( p, 0xF3, X86_TWOB, 0x5B ); +   emit_modrm( p, dst, src ); +} + +void sse2_cvtps2dq( struct x86_function *p, +		    struct x86_reg dst, +		    struct x86_reg src ) +{ +   emit_3ub(p, 0x66, X86_TWOB, 0x5B); +   emit_modrm( p, dst, src ); +} + +void sse2_packssdw( struct x86_function *p, +		    struct x86_reg dst, +		    struct x86_reg src ) +{ +   emit_3ub(p, 0x66, X86_TWOB, 0x6B); +   emit_modrm( p, dst, src ); +} + +void sse2_packsswb( struct x86_function *p, +		    struct x86_reg dst, +		    struct x86_reg src ) +{ +   emit_3ub(p, 0x66, X86_TWOB, 0x63); +   emit_modrm( p, dst, src ); +} + +void sse2_packuswb( struct x86_function *p, +		    struct x86_reg dst, +		    struct x86_reg src ) +{ +   emit_3ub(p, 0x66, X86_TWOB, 0x67); +   emit_modrm( p, dst, src ); +} + +void sse2_rcpps( struct x86_function *p, +                 struct x86_reg dst, +                 struct x86_reg src ) +{ +   emit_2ub(p, X86_TWOB, 0x53); +   emit_modrm( p, dst, src ); +} + +void sse2_rcpss( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_3ub(p, 0xF3, X86_TWOB, 0x53); +   emit_modrm( p, dst, src ); +} + +void sse2_movd( struct x86_function *p, +		struct x86_reg dst, +		struct x86_reg src ) +{ +   emit_2ub(p, 0x66, X86_TWOB); +   emit_op_modrm( p, 0x6e, 0x7e, dst, src ); +} + + + + +/*********************************************************************** + * x87 instructions + */ +void x87_fist( struct x86_function *p, struct x86_reg dst ) +{ +   emit_1ub(p, 0xdb); +   emit_modrm_noreg(p, 2, dst); +} + +void x87_fistp( struct x86_function *p, struct x86_reg dst ) +{ +   emit_1ub(p, 0xdb); +   emit_modrm_noreg(p, 3, dst); +} + +void x87_fild( struct x86_function *p, struct x86_reg arg ) +{ +   emit_1ub(p, 0xdf); +   emit_modrm_noreg(p, 0, arg); +} + +void x87_fldz( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xee); +} + + +void x87_fldcw( struct x86_function *p, struct x86_reg arg ) +{ +   assert(arg.file == file_REG32); +   assert(arg.mod != mod_REG); +   emit_1ub(p, 0xd9); +   emit_modrm_noreg(p, 5, arg); +} + +void x87_fld1( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xe8); +} + +void x87_fldl2e( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xea); +} + +void x87_fldln2( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xed); +} + +void x87_fwait( struct x86_function *p ) +{ +   emit_1ub(p, 0x9b); +} + +void x87_fnclex( struct x86_function *p ) +{ +   emit_2ub(p, 0xdb, 0xe2); +} + +void x87_fclex( struct x86_function *p ) +{ +   x87_fwait(p); +   x87_fnclex(p); +} + + +static void x87_arith_op( struct x86_function *p, struct x86_reg dst, struct x86_reg arg, +			  unsigned char dst0ub0, +			  unsigned char dst0ub1, +			  unsigned char arg0ub0, +			  unsigned char arg0ub1, +			  unsigned char argmem_noreg) +{ +   assert(dst.file == file_x87); + +   if (arg.file == file_x87) { +      if (dst.idx == 0)  +	 emit_2ub(p, dst0ub0, dst0ub1+arg.idx); +      else if (arg.idx == 0)  +	 emit_2ub(p, arg0ub0, arg0ub1+arg.idx); +      else +	 assert(0); +   } +   else if (dst.idx == 0) { +      assert(arg.file == file_REG32); +      emit_1ub(p, 0xd8); +      emit_modrm_noreg(p, argmem_noreg, arg); +   } +   else +      assert(0); +} + +void x87_fmul( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) +{ +   x87_arith_op(p, dst, arg,  +		0xd8, 0xc8, +		0xdc, 0xc8, +		4); +} + +void x87_fsub( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) +{ +   x87_arith_op(p, dst, arg,  +		0xd8, 0xe0, +		0xdc, 0xe8, +		4); +} + +void x87_fsubr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) +{ +   x87_arith_op(p, dst, arg,  +		0xd8, 0xe8, +		0xdc, 0xe0, +		5); +} + +void x87_fadd( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) +{ +   x87_arith_op(p, dst, arg,  +		0xd8, 0xc0, +		0xdc, 0xc0, +		0); +} + +void x87_fdiv( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) +{ +   x87_arith_op(p, dst, arg,  +		0xd8, 0xf0, +		0xdc, 0xf8, +		6); +} + +void x87_fdivr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) +{ +   x87_arith_op(p, dst, arg,  +		0xd8, 0xf8, +		0xdc, 0xf0, +		7); +} + +void x87_fmulp( struct x86_function *p, struct x86_reg dst ) +{ +   assert(dst.file == file_x87); +   assert(dst.idx >= 1); +   emit_2ub(p, 0xde, 0xc8+dst.idx); +} + +void x87_fsubp( struct x86_function *p, struct x86_reg dst ) +{ +   assert(dst.file == file_x87); +   assert(dst.idx >= 1); +   emit_2ub(p, 0xde, 0xe8+dst.idx); +} + +void x87_fsubrp( struct x86_function *p, struct x86_reg dst ) +{ +   assert(dst.file == file_x87); +   assert(dst.idx >= 1); +   emit_2ub(p, 0xde, 0xe0+dst.idx); +} + +void x87_faddp( struct x86_function *p, struct x86_reg dst ) +{ +   assert(dst.file == file_x87); +   assert(dst.idx >= 1); +   emit_2ub(p, 0xde, 0xc0+dst.idx); +} + +void x87_fdivp( struct x86_function *p, struct x86_reg dst ) +{ +   assert(dst.file == file_x87); +   assert(dst.idx >= 1); +   emit_2ub(p, 0xde, 0xf8+dst.idx); +} + +void x87_fdivrp( struct x86_function *p, struct x86_reg dst ) +{ +   assert(dst.file == file_x87); +   assert(dst.idx >= 1); +   emit_2ub(p, 0xde, 0xf0+dst.idx); +} + +void x87_fucom( struct x86_function *p, struct x86_reg arg ) +{ +   assert(arg.file == file_x87); +   emit_2ub(p, 0xdd, 0xe0+arg.idx); +} + +void x87_fucomp( struct x86_function *p, struct x86_reg arg ) +{ +   assert(arg.file == file_x87); +   emit_2ub(p, 0xdd, 0xe8+arg.idx); +} + +void x87_fucompp( struct x86_function *p ) +{ +   emit_2ub(p, 0xda, 0xe9); +} + +void x87_fxch( struct x86_function *p, struct x86_reg arg ) +{ +   assert(arg.file == file_x87); +   emit_2ub(p, 0xd9, 0xc8+arg.idx); +} + +void x87_fabs( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xe1); +} + +void x87_fchs( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xe0); +} + +void x87_fcos( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xff); +} + + +void x87_fprndint( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xfc); +} + +void x87_fscale( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xfd); +} + +void x87_fsin( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xfe); +} + +void x87_fsincos( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xfb); +} + +void x87_fsqrt( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xfa); +} + +void x87_fxtract( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xf4); +} + +/* st0 = (2^st0)-1 + * + * Restrictions: -1.0 <= st0 <= 1.0 + */ +void x87_f2xm1( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xf0); +} + +/* st1 = st1 * log2(st0); + * pop_stack; + */ +void x87_fyl2x( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xf1); +} + +/* st1 = st1 * log2(st0 + 1.0); + * pop_stack; + * + * A fast operation, with restrictions: -.29 < st0 < .29  + */ +void x87_fyl2xp1( struct x86_function *p ) +{ +   emit_2ub(p, 0xd9, 0xf9); +} + + +void x87_fld( struct x86_function *p, struct x86_reg arg ) +{ +   if (arg.file == file_x87)  +      emit_2ub(p, 0xd9, 0xc0 + arg.idx); +   else { +      emit_1ub(p, 0xd9); +      emit_modrm_noreg(p, 0, arg); +   } +} + +void x87_fst( struct x86_function *p, struct x86_reg dst ) +{ +   if (dst.file == file_x87)  +      emit_2ub(p, 0xdd, 0xd0 + dst.idx); +   else { +      emit_1ub(p, 0xd9); +      emit_modrm_noreg(p, 2, dst); +   } +} + +void x87_fstp( struct x86_function *p, struct x86_reg dst ) +{ +   if (dst.file == file_x87)  +      emit_2ub(p, 0xdd, 0xd8 + dst.idx); +   else { +      emit_1ub(p, 0xd9); +      emit_modrm_noreg(p, 3, dst); +   } +} + +void x87_fcom( struct x86_function *p, struct x86_reg dst ) +{ +   if (dst.file == file_x87)  +      emit_2ub(p, 0xd8, 0xd0 + dst.idx); +   else { +      emit_1ub(p, 0xd8); +      emit_modrm_noreg(p, 2, dst); +   } +} + +void x87_fcomp( struct x86_function *p, struct x86_reg dst ) +{ +   if (dst.file == file_x87)  +      emit_2ub(p, 0xd8, 0xd8 + dst.idx); +   else { +      emit_1ub(p, 0xd8); +      emit_modrm_noreg(p, 3, dst); +   } +} + + +void x87_fnstsw( struct x86_function *p, struct x86_reg dst ) +{ +   assert(dst.file == file_REG32); + +   if (dst.idx == reg_AX && +       dst.mod == mod_REG)  +      emit_2ub(p, 0xdf, 0xe0); +   else { +      emit_1ub(p, 0xdd); +      emit_modrm_noreg(p, 7, dst); +   } +} + + + + +/*********************************************************************** + * MMX instructions + */ + +void mmx_emms( struct x86_function *p ) +{ +   assert(p->need_emms); +   emit_2ub(p, 0x0f, 0x77); +   p->need_emms = 0; +} + +void mmx_packssdw( struct x86_function *p, +		   struct x86_reg dst, +		   struct x86_reg src ) +{ +   assert(dst.file == file_MMX &&  +	  (src.file == file_MMX || src.mod != mod_REG)); + +   p->need_emms = 1; + +   emit_2ub(p, X86_TWOB, 0x6b); +   emit_modrm( p, dst, src ); +} + +void mmx_packuswb( struct x86_function *p, +		   struct x86_reg dst, +		   struct x86_reg src ) +{ +   assert(dst.file == file_MMX &&  +	  (src.file == file_MMX || src.mod != mod_REG)); + +   p->need_emms = 1; + +   emit_2ub(p, X86_TWOB, 0x67); +   emit_modrm( p, dst, src ); +} + +void mmx_movd( struct x86_function *p, +	       struct x86_reg dst, +	       struct x86_reg src ) +{ +   p->need_emms = 1; +   emit_1ub(p, X86_TWOB); +   emit_op_modrm( p, 0x6e, 0x7e, dst, src ); +} + +void mmx_movq( struct x86_function *p, +	       struct x86_reg dst, +	       struct x86_reg src ) +{ +   p->need_emms = 1; +   emit_1ub(p, X86_TWOB); +   emit_op_modrm( p, 0x6f, 0x7f, dst, src ); +} + + +/*********************************************************************** + * Helper functions + */ + + +/* Retreive a reference to one of the function arguments, taking into + * account any push/pop activity: + */ +struct x86_reg x86_fn_arg( struct x86_function *p, +			   unsigned arg ) +{ +   return x86_make_disp(x86_make_reg(file_REG32, reg_SP),  +			p->stack_offset + arg * 4);	/* ??? */ +} + + +void x86_init_func( struct x86_function *p ) +{ +   p->size = 0; +   p->store = NULL; +   p->csr = p->store; +} + +void x86_init_func_size( struct x86_function *p, unsigned code_size ) +{ +   p->size = code_size; +   p->store = rtasm_exec_malloc(code_size); +   p->csr = p->store; +} + +void x86_release_func( struct x86_function *p ) +{ +   rtasm_exec_free(p->store); +   p->store = NULL; +   p->csr = NULL; +   p->size = 0; +} + + +void (*x86_get_func( struct x86_function *p ))(void) +{ +   if (DISASSEM && p->store) +      debug_printf("disassemble %p %p\n", p->store, p->csr); +   return (void (*)(void)) (unsigned long) p->store; +} + +#else + +void x86sse_dummy( void ) +{ +} + +#endif diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h new file mode 100644 index 0000000000..606b41eb35 --- /dev/null +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h @@ -0,0 +1,278 @@ +/************************************************************************** + * + * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef _RTASM_X86SSE_H_ +#define _RTASM_X86SSE_H_ + +#if defined(__i386__) || defined(__386__) || defined(i386) + +/* It is up to the caller to ensure that instructions issued are + * suitable for the host cpu.  There are no checks made in this module + * for mmx/sse/sse2 support on the cpu. + */ +struct x86_reg { +   unsigned file:3; +   unsigned idx:3; +   unsigned mod:2;		/* mod_REG if this is just a register */ +   int      disp:24;		/* only +/- 23bits of offset - should be enough... */ +}; + +struct x86_function { +   unsigned size; +   unsigned char *store; +   unsigned char *csr; +   unsigned stack_offset; +   int need_emms; +   const char *fn; +}; + +enum x86_reg_file { +   file_REG32, +   file_MMX, +   file_XMM, +   file_x87 +}; + +/* Values for mod field of modr/m byte + */ +enum x86_reg_mod { +   mod_INDIRECT, +   mod_DISP8, +   mod_DISP32, +   mod_REG +}; + +enum x86_reg_name { +   reg_AX, +   reg_CX, +   reg_DX, +   reg_BX, +   reg_SP, +   reg_BP, +   reg_SI, +   reg_DI +}; + + +enum x86_cc { +   cc_O,			/* overflow */ +   cc_NO,			/* not overflow */ +   cc_NAE,			/* not above or equal / carry */ +   cc_AE,			/* above or equal / not carry */ +   cc_E,			/* equal / zero */ +   cc_NE			/* not equal / not zero */ +}; + +enum sse_cc { +   cc_Equal, +   cc_LessThan, +   cc_LessThanEqual, +   cc_Unordered, +   cc_NotEqual, +   cc_NotLessThan, +   cc_NotLessThanEqual, +   cc_Ordered +}; + +#define cc_Z  cc_E +#define cc_NZ cc_NE + +/* Begin/end/retreive function creation: + */ + + +void x86_init_func( struct x86_function *p ); +void x86_init_func_size( struct x86_function *p, unsigned code_size ); +void x86_release_func( struct x86_function *p ); +void (*x86_get_func( struct x86_function *p ))( void ); + + + +/* Create and manipulate registers and regmem values: + */ +struct x86_reg x86_make_reg( enum x86_reg_file file, +			     enum x86_reg_name idx ); + +struct x86_reg x86_make_disp( struct x86_reg reg, +			      int disp ); + +struct x86_reg x86_deref( struct x86_reg reg ); + +struct x86_reg x86_get_base_reg( struct x86_reg reg ); + + +/* Labels, jumps and fixup: + */ +unsigned char *x86_get_label( struct x86_function *p ); + +void x86_jcc( struct x86_function *p, +	      enum x86_cc cc, +	      unsigned char *label ); + +unsigned char *x86_jcc_forward( struct x86_function *p, +			  enum x86_cc cc ); + +unsigned char *x86_jmp_forward( struct x86_function *p); + +unsigned char *x86_call_forward( struct x86_function *p); + +void x86_fixup_fwd_jump( struct x86_function *p, +			 unsigned char *fixup ); + +void x86_jmp( struct x86_function *p, unsigned char *label ); + +/* void x86_call( struct x86_function *p, void (*label)() ); */ +void x86_call( struct x86_function *p, struct x86_reg reg); + +/* michal: + * Temporary. As I need immediate operands, and dont want to mess with the codegen, + * I load the immediate into general purpose register and use it. + */ +void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ); + + +/* Macro for sse_shufps() and sse2_pshufd(): + */ +#define SHUF(_x,_y,_z,_w)       (((_x)<<0) | ((_y)<<2) | ((_z)<<4) | ((_w)<<6)) +#define SHUF_NOOP               RSW(0,1,2,3) +#define GET_SHUF(swz, idx)      (((swz) >> ((idx)*2)) & 0x3) + +void mmx_emms( struct x86_function *p ); +void mmx_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void mmx_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void mmx_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void mmx_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); + +void sse2_cvtps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse2_cvttps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse2_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse2_packsswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse2_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse2_pshufd( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0, +                  unsigned char shuf ); +void sse2_rcpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse2_rcpss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); + +void sse_addps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_addss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_cvtps2pi( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_divss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_andnps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_andps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_cmpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src, +                unsigned char cc ); +void sse_maxps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_maxss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_minps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_movaps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_movhlps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_movhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_movlhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_movlps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_movss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_movups( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_mulps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_mulss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_orps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_xorps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_subps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_rsqrtps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_rsqrtss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_shufps( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0, +                 unsigned char shuf ); +void sse_pmovmskb( struct x86_function *p, struct x86_reg dest, struct x86_reg src ); + +void x86_add( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void x86_and( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void x86_cmp( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void x86_dec( struct x86_function *p, struct x86_reg reg ); +void x86_inc( struct x86_function *p, struct x86_reg reg ); +void x86_lea( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void x86_mov( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void x86_mul( struct x86_function *p, struct x86_reg src ); +void x86_or( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void x86_pop( struct x86_function *p, struct x86_reg reg ); +void x86_push( struct x86_function *p, struct x86_reg reg ); +void x86_ret( struct x86_function *p ); +void x86_sub( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void x86_test( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void x86_xor( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void x86_sahf( struct x86_function *p ); + +void x87_f2xm1( struct x86_function *p ); +void x87_fabs( struct x86_function *p ); +void x87_fadd( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); +void x87_faddp( struct x86_function *p, struct x86_reg dst ); +void x87_fchs( struct x86_function *p ); +void x87_fclex( struct x86_function *p ); +void x87_fcom( struct x86_function *p, struct x86_reg dst ); +void x87_fcomp( struct x86_function *p, struct x86_reg dst ); +void x87_fcos( struct x86_function *p ); +void x87_fdiv( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); +void x87_fdivp( struct x86_function *p, struct x86_reg dst ); +void x87_fdivr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); +void x87_fdivrp( struct x86_function *p, struct x86_reg dst ); +void x87_fild( struct x86_function *p, struct x86_reg arg ); +void x87_fist( struct x86_function *p, struct x86_reg dst ); +void x87_fistp( struct x86_function *p, struct x86_reg dst ); +void x87_fld( struct x86_function *p, struct x86_reg arg ); +void x87_fld1( struct x86_function *p ); +void x87_fldcw( struct x86_function *p, struct x86_reg arg ); +void x87_fldl2e( struct x86_function *p ); +void x87_fldln2( struct x86_function *p ); +void x87_fldz( struct x86_function *p ); +void x87_fmul( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); +void x87_fmulp( struct x86_function *p, struct x86_reg dst ); +void x87_fnclex( struct x86_function *p ); +void x87_fprndint( struct x86_function *p ); +void x87_fscale( struct x86_function *p ); +void x87_fsin( struct x86_function *p ); +void x87_fsincos( struct x86_function *p ); +void x87_fsqrt( struct x86_function *p ); +void x87_fst( struct x86_function *p, struct x86_reg dst ); +void x87_fstp( struct x86_function *p, struct x86_reg dst ); +void x87_fsub( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); +void x87_fsubp( struct x86_function *p, struct x86_reg dst ); +void x87_fsubr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); +void x87_fsubrp( struct x86_function *p, struct x86_reg dst ); +void x87_fxch( struct x86_function *p, struct x86_reg dst ); +void x87_fxtract( struct x86_function *p ); +void x87_fyl2x( struct x86_function *p ); +void x87_fyl2xp1( struct x86_function *p ); +void x87_fwait( struct x86_function *p ); +void x87_fnstsw( struct x86_function *p, struct x86_reg dst ); +void x87_fucompp( struct x86_function *p ); +void x87_fucomp( struct x86_function *p, struct x86_reg arg ); +void x87_fucom( struct x86_function *p, struct x86_reg arg ); + + + +/* Retreive a reference to one of the function arguments, taking into + * account any push/pop activity.  Note - doesn't track explict + * manipulation of ESP by other instructions. + */ +struct x86_reg x86_fn_arg( struct x86_function *p, unsigned arg ); + +#endif +#endif diff --git a/src/gallium/auxiliary/tgsi/Makefile b/src/gallium/auxiliary/tgsi/Makefile index 12a8bd0409..71f64b747c 100644 --- a/src/gallium/auxiliary/tgsi/Makefile +++ b/src/gallium/auxiliary/tgsi/Makefile @@ -1,3 +1,18 @@ -default: -	cd ../.. ; make +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = tgsi + +C_SOURCES = \ +	exec/tgsi_exec.c \ +	exec/tgsi_sse2.c \ +	util/tgsi_build.c \ +	util/tgsi_dump.c \ +	util/tgsi_parse.c \ +	util/tgsi_transform.c \ +	util/tgsi_util.c + +include ../../Makefile.template + +symlinks: diff --git a/src/gallium/auxiliary/tgsi/SConscript b/src/gallium/auxiliary/tgsi/SConscript new file mode 100644 index 0000000000..8464bfe944 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/SConscript @@ -0,0 +1,14 @@ +Import('*') + +tgsi = env.ConvenienceLibrary( +	target = 'tgsi', +	source = [ +		'exec/tgsi_exec.c', +		'exec/tgsi_sse2.c', +		'util/tgsi_build.c', +		'util/tgsi_dump.c', +		'util/tgsi_parse.c', +		'util/tgsi_util.c', +	]) + +auxiliaries.insert(0, tgsi) diff --git a/src/gallium/auxiliary/tgsi/exec/Makefile b/src/gallium/auxiliary/tgsi/exec/Makefile deleted file mode 100644 index eb8b14e0e8..0000000000 --- a/src/gallium/auxiliary/tgsi/exec/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -default: -	cd ../../.. ; make - diff --git a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c index 62c6a69c63..779b901f2b 100755 --- a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c @@ -32,7 +32,7 @@  #include "tgsi_exec.h"  #include "tgsi_sse2.h" -#include "x86/rtasm/x86sse.h" +#include "rtasm/rtasm_x86sse.h"  #if defined(__i386__) || defined(__386__) @@ -2356,11 +2356,17 @@ tgsi_emit_sse2_fs(           ok = emit_instruction(              func,              &parse.FullToken.FullInstruction ); + +	 if (!ok) { +	    debug_printf("failed to translate tgsi opcode %d\n",  +			 parse.FullToken.FullInstruction.Instruction.Opcode ); +	 }           break;        case TGSI_TOKEN_TYPE_IMMEDIATE:           /* XXX implement this */  	 ok = 0; +	 debug_printf("failed to emit immediate value\n");           break;        default: diff --git a/src/gallium/auxiliary/util/Makefile b/src/gallium/auxiliary/util/Makefile new file mode 100644 index 0000000000..906a46d6b4 --- /dev/null +++ b/src/gallium/auxiliary/util/Makefile @@ -0,0 +1,15 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = util + +C_SOURCES = \ +	p_debug.c \ +	p_tile.c \ +	p_util.c \ +	u_mm.c + +include ../../Makefile.template + +symlinks: + diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript new file mode 100644 index 0000000000..4717941434 --- /dev/null +++ b/src/gallium/auxiliary/util/SConscript @@ -0,0 +1,12 @@ +Import('*') + +util = env.ConvenienceLibrary( +	target = 'util', +	source = [ +		'p_debug.c', +		'p_tile.c', +		'p_util.c', +		'u_mm.c', +	]) + +auxiliaries.insert(0, util) diff --git a/src/gallium/auxiliary/pipebuffer/linked_list.h b/src/gallium/auxiliary/util/u_double_list.h index e99817fb13..8cb10c9820 100644 --- a/src/gallium/auxiliary/pipebuffer/linked_list.h +++ b/src/gallium/auxiliary/util/u_double_list.h @@ -34,8 +34,8 @@   * be protected using an external mutex.   */ -#ifndef LINKED_LIST_H_ -#define LINKED_LIST_H_ +#ifndef _U_DOUBLE_LIST_H_ +#define _U_DOUBLE_LIST_H_  #include <stddef.h> @@ -88,4 +88,4 @@ struct list_head      ((__type *)(((char *)(__item)) - offsetof(__type, __field))) -#endif /*LINKED_LIST_H_*/ +#endif /*_U_DOUBLE_LIST_H_*/ diff --git a/src/gallium/auxiliary/util/u_mm.c b/src/gallium/auxiliary/util/u_mm.c new file mode 100644 index 0000000000..b49ae074e0 --- /dev/null +++ b/src/gallium/auxiliary/util/u_mm.c @@ -0,0 +1,283 @@ +/************************************************************************** + * + * Copyright (C) 1999 Wittawat Yamwong + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,  + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR  + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "pipe/p_compiler.h" +#include "pipe/p_util.h" +#include "pipe/p_debug.h" + +#include "util/u_mm.h" + + +void +mmDumpMemInfo(const struct mem_block *heap) +{ +   debug_printf("Memory heap %p:\n", (void *)heap); +   if (heap == 0) { +      debug_printf("  heap == 0\n"); +   } else { +      const struct mem_block *p; + +      for(p = heap->next; p != heap; p = p->next) { +	 debug_printf("  Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, +		 p->free ? 'F':'.', +		 p->reserved ? 'R':'.'); +      } + +      debug_printf("\nFree list:\n"); + +      for(p = heap->next_free; p != heap; p = p->next_free) { +	 debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, +		 p->free ? 'F':'.', +		 p->reserved ? 'R':'.'); +      } + +   } +   debug_printf("End of memory blocks\n"); +} + +struct mem_block * +mmInit(int ofs, int size) +{ +   struct mem_block *heap, *block; +   +   if (size <= 0)  +      return NULL; + +   heap = CALLOC_STRUCT(mem_block); +   if (!heap)  +      return NULL; +    +   block = CALLOC_STRUCT(mem_block); +   if (!block) { +      FREE(heap); +      return NULL; +   } + +   heap->next = block; +   heap->prev = block; +   heap->next_free = block; +   heap->prev_free = block; + +   block->heap = heap; +   block->next = heap; +   block->prev = heap; +   block->next_free = heap; +   block->prev_free = heap; + +   block->ofs = ofs; +   block->size = size; +   block->free = 1; + +   return heap; +} + + +static struct mem_block * +SliceBlock(struct mem_block *p,  +           int startofs, int size,  +           int reserved, int alignment) +{ +   struct mem_block *newblock; + +   /* break left  [p, newblock, p->next], then p = newblock */ +   if (startofs > p->ofs) { +      newblock = CALLOC_STRUCT(mem_block); +      if (!newblock) +	 return NULL; +      newblock->ofs = startofs; +      newblock->size = p->size - (startofs - p->ofs); +      newblock->free = 1; +      newblock->heap = p->heap; + +      newblock->next = p->next; +      newblock->prev = p; +      p->next->prev = newblock; +      p->next = newblock; + +      newblock->next_free = p->next_free; +      newblock->prev_free = p; +      p->next_free->prev_free = newblock; +      p->next_free = newblock; + +      p->size -= newblock->size; +      p = newblock; +   } + +   /* break right, also [p, newblock, p->next] */ +   if (size < p->size) { +      newblock = CALLOC_STRUCT(mem_block); +      if (!newblock) +	 return NULL; +      newblock->ofs = startofs + size; +      newblock->size = p->size - size; +      newblock->free = 1; +      newblock->heap = p->heap; + +      newblock->next = p->next; +      newblock->prev = p; +      p->next->prev = newblock; +      p->next = newblock; + +      newblock->next_free = p->next_free; +      newblock->prev_free = p; +      p->next_free->prev_free = newblock; +      p->next_free = newblock; +	  +      p->size = size; +   } + +   /* p = middle block */ +   p->free = 0; + +   /* Remove p from the free list:  +    */ +   p->next_free->prev_free = p->prev_free; +   p->prev_free->next_free = p->next_free; + +   p->next_free = 0; +   p->prev_free = 0; + +   p->reserved = reserved; +   return p; +} + + +struct mem_block * +mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch) +{ +   struct mem_block *p; +   const int mask = (1 << align2)-1; +   int startofs = 0; +   int endofs; + +   if (!heap || align2 < 0 || size <= 0) +      return NULL; + +   for (p = heap->next_free; p != heap; p = p->next_free) { +      assert(p->free); + +      startofs = (p->ofs + mask) & ~mask; +      if ( startofs < startSearch ) { +	 startofs = startSearch; +      } +      endofs = startofs+size; +      if (endofs <= (p->ofs+p->size)) +	 break; +   } + +   if (p == heap)  +      return NULL; + +   assert(p->free); +   p = SliceBlock(p,startofs,size,0,mask+1); + +   return p; +} + + +struct mem_block * +mmFindBlock(struct mem_block *heap, int start) +{ +   struct mem_block *p; + +   for (p = heap->next; p != heap; p = p->next) { +      if (p->ofs == start)  +	 return p; +   } + +   return NULL; +} + + +static INLINE int +Join2Blocks(struct mem_block *p) +{ +   /* XXX there should be some assertions here */ + +   /* NOTE: heap->free == 0 */ + +   if (p->free && p->next->free) { +      struct mem_block *q = p->next; + +      assert(p->ofs + p->size == q->ofs); +      p->size += q->size; + +      p->next = q->next; +      q->next->prev = p; + +      q->next_free->prev_free = q->prev_free;  +      q->prev_free->next_free = q->next_free; +      +      FREE(q); +      return 1; +   } +   return 0; +} + +int +mmFreeMem(struct mem_block *b) +{ +   if (!b) +      return 0; + +   if (b->free) { +      debug_printf("block already free\n"); +      return -1; +   } +   if (b->reserved) { +      debug_printf("block is reserved\n"); +      return -1; +   } + +   b->free = 1; +   b->next_free = b->heap->next_free; +   b->prev_free = b->heap; +   b->next_free->prev_free = b; +   b->prev_free->next_free = b; + +   Join2Blocks(b); +   if (b->prev != b->heap) +      Join2Blocks(b->prev); + +   return 0; +} + + +void +mmDestroy(struct mem_block *heap) +{ +   struct mem_block *p; + +   if (!heap) +      return; + +   for (p = heap->next; p != heap; ) { +      struct mem_block *next = p->next; +      FREE(p); +      p = next; +   } + +   FREE(heap); +} diff --git a/src/gallium/auxiliary/util/u_mm.h b/src/gallium/auxiliary/util/u_mm.h new file mode 100644 index 0000000000..b226b101cb --- /dev/null +++ b/src/gallium/auxiliary/util/u_mm.h @@ -0,0 +1,91 @@ +/************************************************************************** + * + * Copyright (C) 1999 Wittawat Yamwong + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,  + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR  + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/** + * @file + * Memory manager code.  Primarily used by device drivers to manage texture + * heaps, etc. + */ + + +#ifndef _U_MM_H_ +#define _U_MM_H_ + + +struct mem_block { +   struct mem_block *next, *prev; +   struct mem_block *next_free, *prev_free; +   struct mem_block *heap; +   int ofs,size; +   unsigned int free:1; +   unsigned int reserved:1; +}; + + + +/**  + * input: total size in bytes + * return: a heap pointer if OK, NULL if error + */ +extern struct mem_block *mmInit(int ofs, int size); + +/** + * Allocate 'size' bytes with 2^align2 bytes alignment, + * restrict the search to free memory after 'startSearch' + * depth and back buffers should be in different 4mb banks + * to get better page hits if possible + * input:	size = size of block + *       	align2 = 2^align2 bytes alignment + *		startSearch = linear offset from start of heap to begin search + * return: pointer to the allocated block, 0 if error + */ +extern struct mem_block *mmAllocMem(struct mem_block *heap, int size, int align2,  +                            int startSearch); + +/** + * Free block starts at offset + * input: pointer to a block + * return: 0 if OK, -1 if error + */ +extern int mmFreeMem(struct mem_block *b); + +/** + * Free block starts at offset + * input: pointer to a heap, start offset + * return: pointer to a block + */ +extern struct mem_block *mmFindBlock(struct mem_block *heap, int start); + +/** + * destroy MM + */ +extern void mmDestroy(struct mem_block *mmInit); + +/** + * For debuging purpose. + */ +extern void mmDumpMemInfo(const struct mem_block *mmInit); + +#endif diff --git a/src/gallium/auxiliary/util/u_simple_list.h b/src/gallium/auxiliary/util/u_simple_list.h new file mode 100644 index 0000000000..f5f43b0faa --- /dev/null +++ b/src/gallium/auxiliary/util/u_simple_list.h @@ -0,0 +1,197 @@ +/** + * \file simple_list.h + * Simple macros for type-safe, intrusive lists. + * + *  Intended to work with a list sentinal which is created as an empty + *  list.  Insert & delete are O(1). + *   + * \author + *  (C) 1997, Keith Whitwell + */ + +/* + * Mesa 3-D graphics library + * Version:  3.5 + * + * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef _U_SIMPLE_LIST_H_ +#define _U_SIMPLE_LIST_H_ + +/** + * Remove an element from list. + * + * \param elem element to remove. + */ +#define remove_from_list(elem)			\ +do {						\ +   (elem)->next->prev = (elem)->prev;		\ +   (elem)->prev->next = (elem)->next;		\ +} while (0) + +/** + * Insert an element to the list head. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_head(list, elem)		\ +do {						\ +   (elem)->prev = list;				\ +   (elem)->next = (list)->next;			\ +   (list)->next->prev = elem;			\ +   (list)->next = elem;				\ +} while(0) + +/** + * Insert an element to the list tail. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_tail(list, elem)		\ +do {						\ +   (elem)->next = list;				\ +   (elem)->prev = (list)->prev;			\ +   (list)->prev->next = elem;			\ +   (list)->prev = elem;				\ +} while(0) + +/** + * Move an element to the list head. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_head(list, elem)		\ +do {						\ +   remove_from_list(elem);			\ +   insert_at_head(list, elem);			\ +} while (0) + +/** + * Move an element to the list tail. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_tail(list, elem)		\ +do {						\ +   remove_from_list(elem);			\ +   insert_at_tail(list, elem);			\ +} while (0) + +/** + * Make a empty list empty. + * + * \param sentinal list (sentinal element). + */ +#define make_empty_list(sentinal)		\ +do {						\ +   (sentinal)->next = sentinal;			\ +   (sentinal)->prev = sentinal;			\ +} while (0) + +/** + * Get list first element. + * + * \param list list. + * + * \return pointer to first element. + */ +#define first_elem(list)       ((list)->next) + +/** + * Get list last element. + * + * \param list list. + * + * \return pointer to last element. + */ +#define last_elem(list)        ((list)->prev) + +/** + * Get next element. + * + * \param elem element. + * + * \return pointer to next element. + */ +#define next_elem(elem)        ((elem)->next) + +/** + * Get previous element. + * + * \param elem element. + * + * \return pointer to previous element. + */ +#define prev_elem(elem)        ((elem)->prev) + +/** + * Test whether element is at end of the list. + *  + * \param list list. + * \param elem element. + *  + * \return non-zero if element is at end of list, or zero otherwise. + */ +#define at_end(list, elem)     ((elem) == (list)) + +/** + * Test if a list is empty. + *  + * \param list list. + *  + * \return non-zero if list empty, or zero otherwise. + */ +#define is_empty_list(list)    ((list)->next == (list)) + +/** + * Walk through the elements of a list. + * + * \param ptr pointer to the current element. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach(ptr, list)     \ +        for( ptr=(list)->next ;  ptr!=list ;  ptr=(ptr)->next ) + +/** + * Walk through the elements of a list. + * + * Same as #foreach but lets you unlink the current value during a list + * traversal.  Useful for freeing a list, element by element. + *  + * \param ptr pointer to the current element. + * \param t temporary pointer. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach_s(ptr, t, list)   \ +        for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next) + +#endif /* _U_SIMPLE_LIST_H_ */ diff --git a/src/gallium/drivers/Makefile b/src/gallium/drivers/Makefile index 58df6c5009..6161cb6ff8 100644 --- a/src/gallium/drivers/Makefile +++ b/src/gallium/drivers/Makefile @@ -2,12 +2,7 @@ TOP = ../../..  include $(TOP)/configs/current -ifeq ($(CONFIG_NAME), linux-cell) -CELL_DIR = cell -endif - -SUBDIRS = softpipe i915simple i965simple nv30 nv40 nv50 \ -	  failover pipebuffer $(CELL_DIR) +SUBDIRS = $(GALLIUM_DRIVER_DIRS)  default: subdirs diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h index 74b131fbef..9a4004535e 100644 --- a/src/gallium/drivers/cell/common.h +++ b/src/gallium/drivers/cell/common.h @@ -87,10 +87,13 @@  #define CELL_CMD_STATE_TEXTURE       13  #define CELL_CMD_STATE_VERTEX_INFO   14  #define CELL_CMD_STATE_VIEWPORT      15 -#define CELL_CMD_STATE_VS_ARRAY_INFO 16 -#define CELL_CMD_STATE_BLEND         17 -#define CELL_CMD_VS_EXECUTE          18 -#define CELL_CMD_STATE_ATTRIB_FETCH  19 +#define CELL_CMD_STATE_UNIFORMS      16 +#define CELL_CMD_STATE_VS_ARRAY_INFO 17 +#define CELL_CMD_STATE_BIND_VS       18 +#define CELL_CMD_STATE_BLEND         19 +#define CELL_CMD_STATE_ATTRIB_FETCH  20 +#define CELL_CMD_VS_EXECUTE          21 +#define CELL_CMD_FLUSH_BUFFER_RANGE  22  #define CELL_NUM_BUFFERS 4 @@ -134,7 +137,7 @@ struct cell_array_info     uint pitch;         /**< Byte pitch from one entry to the next. */     uint size;     uint function_offset; -} ALIGN16_ATTRIB; +};  struct cell_attribute_fetch_code { @@ -142,32 +145,37 @@ struct cell_attribute_fetch_code {     uint size;  }; + +struct cell_buffer_range { +   uint64_t base; +   unsigned size; +}; + +  struct cell_shader_info  { -   unsigned num_outputs; -     uint64_t declarations; -   unsigned num_declarations;     uint64_t instructions; -   unsigned num_instructions; -   uint64_t uniforms;     uint64_t  immediates; + +   unsigned num_outputs; +   unsigned num_declarations; +   unsigned num_instructions;     unsigned num_immediates; -} ALIGN16_ATTRIB; +};  #define SPU_VERTS_PER_BATCH 64  struct cell_command_vs  {     uint64_t opcode;       /**< CELL_CMD_VS_EXECUTE */ -   struct cell_shader_info   shader; +   uint64_t vOut[SPU_VERTS_PER_BATCH];     unsigned num_elts;     unsigned elts[SPU_VERTS_PER_BATCH]; -   uint64_t vOut[SPU_VERTS_PER_BATCH];     float plane[12][4];     unsigned nr_planes;     unsigned nr_attrs; -} ALIGN16_ATTRIB; +};  struct cell_command_render diff --git a/src/gallium/drivers/cell/ppu/Makefile b/src/gallium/drivers/cell/ppu/Makefile index 196ab777f5..164dde762c 100644 --- a/src/gallium/drivers/cell/ppu/Makefile +++ b/src/gallium/drivers/cell/ppu/Makefile @@ -1,6 +1,6 @@  # Gallium3D Cell driver: PPU code -# This makefile builds the g3dcell.a library which gets pulled into +# This makefile builds the libcell.a library which gets pulled into  # the main libGL.so library @@ -8,10 +8,14 @@ TOP = ../../../../..  include $(TOP)/configs/linux-cell -#PROG = gl4 +# This is the "top-level" cell PPU driver code, will get pulled into libGL.so +# by the winsys Makefile. +CELL_LIB = ../libcell.a -CELL_LIB = libcell.a +# This is the SPU code.  We'd like to be able to put this into the libcell.a +# archive with the PPU code, but nesting .a libs doesn't seem to work. +# So, it's pulled into libGL.so in gallium/winsys/xlib/Makefile  SPU_CODE_MODULE = ../spu/g3d_spu.a @@ -21,14 +25,10 @@ SOURCES = \  	cell_context.c \  	cell_draw_arrays.c \  	cell_flush.c \ -	cell_state_blend.c \ -	cell_state_clip.c \  	cell_state_derived.c \  	cell_state_emit.c \ -	cell_state_fs.c \ -	cell_state_rasterizer.c \ -	cell_state_sampler.c \ -	cell_state_surface.c \ +	cell_state_shader.c \ +	cell_pipe_state.c \  	cell_state_vertex.c \  	cell_spu.c \  	cell_surface.c \ @@ -56,7 +56,7 @@ default: $(CELL_LIB)  $(CELL_LIB): $(OBJECTS) $(SPU_CODE_MODULE) -#	ar -ru $(CELL_LIB) $(OBJECTS) $(SPU_CODE_MODULE) +#	ar -ru $(CELL_LIB) $(OBJECTS) $(SPU_CODE_MODULE) # doesn't work  	ar -ru $(CELL_LIB) $(OBJECTS)  #$(PROG): $(PPU_OBJECTS) diff --git a/src/gallium/drivers/cell/ppu/cell_clear.c b/src/gallium/drivers/cell/ppu/cell_clear.c index e588a30d5b..3ffe09add6 100644 --- a/src/gallium/drivers/cell/ppu/cell_clear.c +++ b/src/gallium/drivers/cell/ppu/cell_clear.c @@ -41,6 +41,7 @@  #include "cell_batch.h"  #include "cell_flush.h"  #include "cell_spu.h" +#include "cell_state.h"  void diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c index e1eb22f468..98c314f45c 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.c +++ b/src/gallium/drivers/cell/ppu/cell_context.c @@ -48,6 +48,7 @@  #include "cell_state.h"  #include "cell_surface.h"  #include "cell_spu.h" +#include "cell_pipe_state.h"  #include "cell_texture.h"  #include "cell_vbuf.h" @@ -198,40 +199,6 @@ cell_create_context(struct pipe_winsys *winsys, struct cell_winsys *cws)     /* state setters */ -   cell->pipe.create_blend_state = cell_create_blend_state; -   cell->pipe.bind_blend_state   = cell_bind_blend_state; -   cell->pipe.delete_blend_state = cell_delete_blend_state; - -   cell->pipe.create_sampler_state = cell_create_sampler_state; -   cell->pipe.bind_sampler_state   = cell_bind_sampler_state; -   cell->pipe.delete_sampler_state = cell_delete_sampler_state; - -   cell->pipe.create_depth_stencil_alpha_state = cell_create_depth_stencil_alpha_state; -   cell->pipe.bind_depth_stencil_alpha_state   = cell_bind_depth_stencil_alpha_state; -   cell->pipe.delete_depth_stencil_alpha_state = cell_delete_depth_stencil_alpha_state; - -   cell->pipe.create_rasterizer_state = cell_create_rasterizer_state; -   cell->pipe.bind_rasterizer_state   = cell_bind_rasterizer_state; -   cell->pipe.delete_rasterizer_state = cell_delete_rasterizer_state; - -   cell->pipe.create_fs_state = cell_create_fs_state; -   cell->pipe.bind_fs_state   = cell_bind_fs_state; -   cell->pipe.delete_fs_state = cell_delete_fs_state; - -   cell->pipe.create_vs_state = cell_create_vs_state; -   cell->pipe.bind_vs_state   = cell_bind_vs_state; -   cell->pipe.delete_vs_state = cell_delete_vs_state; - -   cell->pipe.set_blend_color = cell_set_blend_color; -   cell->pipe.set_clip_state = cell_set_clip_state; -   cell->pipe.set_constant_buffer = cell_set_constant_buffer; - -   cell->pipe.set_framebuffer_state = cell_set_framebuffer_state; - -   cell->pipe.set_polygon_stipple = cell_set_polygon_stipple; -   cell->pipe.set_scissor_state = cell_set_scissor_state; -   cell->pipe.set_viewport_state = cell_set_viewport_state; -     cell->pipe.set_vertex_buffer = cell_set_vertex_buffer;     cell->pipe.set_vertex_element = cell_set_vertex_element; @@ -241,20 +208,16 @@ cell_create_context(struct pipe_winsys *winsys, struct cell_winsys *cws)     cell->pipe.clear = cell_clear_surface;     cell->pipe.flush = cell_flush; -   /* textures */ -   cell->pipe.texture_create = cell_texture_create; -   cell->pipe.texture_release = cell_texture_release; -   cell->pipe.get_tex_surface = cell_get_tex_surface; - -   cell->pipe.set_sampler_texture = cell_set_sampler_texture; -  #if 0     cell->pipe.begin_query = cell_begin_query;     cell->pipe.end_query = cell_end_query;     cell->pipe.wait_query = cell_wait_query;  #endif +   cell_init_state_functions(cell); +   cell_init_shader_functions(cell);     cell_init_surface_functions(cell); +   cell_init_texture_functions(cell);     cell->draw = cell_draw_create(cell); diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h index 91f8e542a2..3b687bb868 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.h +++ b/src/gallium/drivers/cell/ppu/cell_context.h @@ -36,7 +36,7 @@  #include "draw/draw_vbuf.h"  #include "cell_winsys.h"  #include "cell/common.h" -#include "ppc/rtasm/spe_asm.h" +#include "rtasm/rtasm_ppc_spe.h"  struct cell_vbuf_render; diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c index f12613649b..cbd387f014 100644 --- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c +++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c @@ -49,9 +49,12 @@ cell_map_constant_buffers(struct cell_context *sp)     struct pipe_winsys *ws = sp->pipe.winsys;     uint i;     for (i = 0; i < 2; i++) { -      if (sp->constants[i].size) +      if (sp->constants[i].size) {           sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer,                                                    PIPE_BUFFER_USAGE_CPU_READ); +         cell_flush_buffer_range(sp, sp->mapped_constants[i],  +                                 sp->constants[i].buffer->size); +      }     }     draw_set_mapped_constant_buffer(sp->draw, @@ -124,6 +127,7 @@ cell_draw_elements(struct pipe_context *pipe,           void *buf = pipe->winsys->buffer_map(pipe->winsys,                                                sp->vertex_buffer[i].buffer,                                                PIPE_BUFFER_USAGE_CPU_READ); +	 cell_flush_buffer_range(sp, buf, sp->vertex_buffer[i].buffer->size);           draw_set_mapped_vertex_buffer(draw, i, buf);        }     } diff --git a/src/gallium/drivers/cell/ppu/cell_flush.c b/src/gallium/drivers/cell/ppu/cell_flush.c index 20f27531fc..66a5627d84 100644 --- a/src/gallium/drivers/cell/ppu/cell_flush.c +++ b/src/gallium/drivers/cell/ppu/cell_flush.c @@ -82,3 +82,17 @@ cell_flush_int(struct pipe_context *pipe, unsigned flags)     flushing = FALSE;  } + + +void +cell_flush_buffer_range(struct cell_context *cell, void *ptr, +			unsigned size) +{ +   uint64_t batch[1 + (ROUNDUP8(sizeof(struct cell_buffer_range)) / 8)]; +   struct cell_buffer_range *br = (struct cell_buffer_range *) & batch[1]; + +   batch[0] = CELL_CMD_FLUSH_BUFFER_RANGE; +   br->base = (uintptr_t) ptr; +   br->size = size; +   cell_batch_append(cell, batch, sizeof(batch)); +} diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c new file mode 100644 index 0000000000..95bfc29fbe --- /dev/null +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -0,0 +1,326 @@ +/************************************************************************** + *  + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *  + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *  + **************************************************************************/ + +/* Authors: + *  Keith Whitwell <keith@tungstengraphics.com> + *  Brian Paul + */ + +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" +#include "draw/draw_context.h" +#include "cell_context.h" +#include "cell_state.h" +#include "cell_texture.h" + + + +static void * +cell_create_blend_state(struct pipe_context *pipe, +                        const struct pipe_blend_state *blend) +{ +   return mem_dup(blend, sizeof(*blend)); +} + + +static void +cell_bind_blend_state(struct pipe_context *pipe, void *blend) +{ +   struct cell_context *cell = cell_context(pipe); + +   draw_flush(cell->draw); + +   cell->blend = (const struct pipe_blend_state *)blend; + +   cell->dirty |= CELL_NEW_BLEND; +} + + +static void +cell_delete_blend_state(struct pipe_context *pipe, void *blend) +{ +   FREE(blend); +} + + +static void +cell_set_blend_color(struct pipe_context *pipe, +                     const struct pipe_blend_color *blend_color) +{ +   struct cell_context *cell = cell_context(pipe); + +   draw_flush(cell->draw); + +   cell->blend_color = *blend_color; + +   cell->dirty |= CELL_NEW_BLEND; +} + + + + +static void * +cell_create_depth_stencil_alpha_state(struct pipe_context *pipe, +                 const struct pipe_depth_stencil_alpha_state *depth_stencil) +{ +   return mem_dup(depth_stencil, sizeof(*depth_stencil)); +} + + +static void +cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe, +                                    void *depth_stencil) +{ +   struct cell_context *cell = cell_context(pipe); + +   draw_flush(cell->draw); + +   cell->depth_stencil +      = (const struct pipe_depth_stencil_alpha_state *) depth_stencil; + +   cell->dirty |= CELL_NEW_DEPTH_STENCIL; +} + + +static void +cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *depth) +{ +   FREE(depth); +} + + +static void cell_set_clip_state( struct pipe_context *pipe, +			     const struct pipe_clip_state *clip ) +{ +   struct cell_context *cell = cell_context(pipe); + +   /* pass the clip state to the draw module */ +   draw_set_clip_state(cell->draw, clip); +} + + + +/* Called when driver state tracker notices changes to the viewport + * matrix: + */ +static void +cell_set_viewport_state( struct pipe_context *pipe, +                         const struct pipe_viewport_state *viewport ) +{ +   struct cell_context *cell = cell_context(pipe); + +   cell->viewport = *viewport; /* struct copy */ +   cell->dirty |= CELL_NEW_VIEWPORT; + +   /* pass the viewport info to the draw module */ +   draw_set_viewport_state(cell->draw, viewport); + +   /* Using tnl/ and vf/ modules is temporary while getting started. +    * Full pipe will have vertex shader, vertex fetch of its own. +    */ +} + + +static void +cell_set_scissor_state( struct pipe_context *pipe, +                        const struct pipe_scissor_state *scissor ) +{ +   struct cell_context *cell = cell_context(pipe); + +   memcpy( &cell->scissor, scissor, sizeof(*scissor) ); +   cell->dirty |= CELL_NEW_SCISSOR; +} + + +static void +cell_set_polygon_stipple( struct pipe_context *pipe, +                          const struct pipe_poly_stipple *stipple ) +{ +   struct cell_context *cell = cell_context(pipe); + +   memcpy( &cell->poly_stipple, stipple, sizeof(*stipple) ); +   cell->dirty |= CELL_NEW_STIPPLE; +} + + + +static void * +cell_create_rasterizer_state(struct pipe_context *pipe, +                             const struct pipe_rasterizer_state *setup) +{ +   struct pipe_rasterizer_state *state +      = MALLOC(sizeof(struct pipe_rasterizer_state)); +   memcpy(state, setup, sizeof(struct pipe_rasterizer_state)); +   return state; +} + + +static void +cell_bind_rasterizer_state(struct pipe_context *pipe, void *setup) +{ +   struct cell_context *cell = cell_context(pipe); + +   /* pass-through to draw module */ +   draw_set_rasterizer_state(cell->draw, setup); + +   cell->rasterizer = (struct pipe_rasterizer_state *)setup; + +   cell->dirty |= CELL_NEW_RASTERIZER; +} + + +static void +cell_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer) +{ +   FREE(rasterizer); +} + + + +static void * +cell_create_sampler_state(struct pipe_context *pipe, +                          const struct pipe_sampler_state *sampler) +{ +   return mem_dup(sampler, sizeof(*sampler)); +} + + +static void +cell_bind_sampler_state(struct pipe_context *pipe, +                            unsigned unit, void *sampler) +{ +   struct cell_context *cell = cell_context(pipe); + +   draw_flush(cell->draw); + +   assert(unit < PIPE_MAX_SAMPLERS); +   cell->sampler[unit] = (struct pipe_sampler_state *)sampler; + +   cell->dirty |= CELL_NEW_SAMPLER; +} + + +static void +cell_delete_sampler_state(struct pipe_context *pipe, +                              void *sampler) +{ +   FREE( sampler ); +} + + + +static void +cell_set_sampler_texture(struct pipe_context *pipe, +                         unsigned sampler, +                         struct pipe_texture *texture) +{ +   struct cell_context *cell = cell_context(pipe); + +   draw_flush(cell->draw); + +   pipe_texture_reference(pipe, +                          (struct pipe_texture **) &cell->texture[sampler], +                          texture); + +   cell_update_texture_mapping(cell); + +   cell->dirty |= CELL_NEW_TEXTURE; +} + + + +static void +cell_set_framebuffer_state(struct pipe_context *pipe, +                           const struct pipe_framebuffer_state *fb) +{ +   struct cell_context *cell = cell_context(pipe); + +   if (1 /*memcmp(&cell->framebuffer, fb, sizeof(*fb))*/) { +      struct pipe_surface *csurf = fb->cbufs[0]; +      struct pipe_surface *zsurf = fb->zsbuf; +      uint i; + +      /* unmap old surfaces */ +      for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { +         if (cell->framebuffer.cbufs[i] && cell->cbuf_map[i]) { +            pipe_surface_unmap(cell->framebuffer.cbufs[i]); +            cell->cbuf_map[i] = NULL; +         } +      } + +      if (cell->framebuffer.zsbuf && cell->zsbuf_map) { +         pipe_surface_unmap(cell->framebuffer.zsbuf); +         cell->zsbuf_map = NULL; +      } + +      /* update my state */ +      cell->framebuffer = *fb; + +      /* map new surfaces */ +      if (csurf) +         cell->cbuf_map[0] = pipe_surface_map(csurf); + +      if (zsurf) +         cell->zsbuf_map = pipe_surface_map(zsurf); + +      cell->dirty |= CELL_NEW_FRAMEBUFFER; +   } +} + + + +void +cell_init_state_functions(struct cell_context *cell) +{ +   cell->pipe.create_blend_state = cell_create_blend_state; +   cell->pipe.bind_blend_state   = cell_bind_blend_state; +   cell->pipe.delete_blend_state = cell_delete_blend_state; + +   cell->pipe.create_sampler_state = cell_create_sampler_state; +   cell->pipe.bind_sampler_state   = cell_bind_sampler_state; +   cell->pipe.delete_sampler_state = cell_delete_sampler_state; + +   cell->pipe.set_sampler_texture = cell_set_sampler_texture; + +   cell->pipe.create_depth_stencil_alpha_state = cell_create_depth_stencil_alpha_state; +   cell->pipe.bind_depth_stencil_alpha_state   = cell_bind_depth_stencil_alpha_state; +   cell->pipe.delete_depth_stencil_alpha_state = cell_delete_depth_stencil_alpha_state; + +   cell->pipe.create_rasterizer_state = cell_create_rasterizer_state; +   cell->pipe.bind_rasterizer_state   = cell_bind_rasterizer_state; +   cell->pipe.delete_rasterizer_state = cell_delete_rasterizer_state; + +   cell->pipe.set_blend_color = cell_set_blend_color; +   cell->pipe.set_clip_state = cell_set_clip_state; + +   cell->pipe.set_framebuffer_state = cell_set_framebuffer_state; + +   cell->pipe.set_polygon_stipple = cell_set_polygon_stipple; +   cell->pipe.set_scissor_state = cell_set_scissor_state; +   cell->pipe.set_viewport_state = cell_set_viewport_state; +} + diff --git a/src/gallium/drivers/cell/ppu/cell_state_surface.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.h index 287610b76b..1889bd52ff 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_surface.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.h @@ -1,8 +1,8 @@  /**************************************************************************   *  - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.   * All Rights Reserved. - *  + *   * Permission is hereby granted, free of charge, to any person obtaining a   * copy of this software and associated documentation files (the   * "Software"), to deal in the Software without restriction, including @@ -26,46 +26,14 @@   **************************************************************************/ -#include "pipe/p_inlines.h" -#include "cell_context.h" -#include "cell_state.h" - - -void -cell_set_framebuffer_state(struct pipe_context *pipe, -                           const struct pipe_framebuffer_state *fb) -{ -   struct cell_context *cell = cell_context(pipe); - -   if (1 /*memcmp(&cell->framebuffer, fb, sizeof(*fb))*/) { -      struct pipe_surface *csurf = fb->cbufs[0]; -      struct pipe_surface *zsurf = fb->zsbuf; -      uint i; - -      /* unmap old surfaces */ -      for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { -         if (cell->framebuffer.cbufs[i] && cell->cbuf_map[i]) { -            pipe_surface_unmap(cell->framebuffer.cbufs[i]); -            cell->cbuf_map[i] = NULL; -         } -      } - -      if (cell->framebuffer.zsbuf && cell->zsbuf_map) { -         pipe_surface_unmap(cell->framebuffer.zsbuf); -         cell->zsbuf_map = NULL; -      } +#ifndef CELL_PIPE_STATE_H +#define CELL_PIPE_STATE_H -      /* update my state */ -      cell->framebuffer = *fb; -      /* map new surfaces */ -      if (csurf) -         cell->cbuf_map[0] = pipe_surface_map(csurf); +struct cell_context; -      if (zsurf) -         cell->zsbuf_map = pipe_surface_map(zsurf); +extern void +cell_init_state_functions(struct cell_context *cell); -      cell->dirty |= CELL_NEW_FRAMEBUFFER; -   } -} +#endif /* CELL_PIPE_STATE_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_state.h b/src/gallium/drivers/cell/ppu/cell_state.h index 3a71ba14fa..31ce505e21 100644 --- a/src/gallium/drivers/cell/ppu/cell_state.h +++ b/src/gallium/drivers/cell/ppu/cell_state.h @@ -1,3 +1,29 @@ +/************************************************************************** + *  + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + *  + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *  + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *  + **************************************************************************/  #ifndef CELL_STATE_H @@ -22,82 +48,6 @@  #define CELL_NEW_VERTEX_INFO   0x8000 - -extern void -cell_set_framebuffer_state( struct pipe_context *, -                            const struct pipe_framebuffer_state * ); - - - -extern void * -cell_create_blend_state(struct pipe_context *, const struct pipe_blend_state *); -extern void cell_bind_blend_state(struct pipe_context *, void *); -extern void cell_delete_blend_state(struct pipe_context *, void *); - -extern void cell_set_blend_color( struct pipe_context *pipe, -                                  const struct pipe_blend_color *blend_color ); - - -void * -cell_create_sampler_state(struct pipe_context *, -                          const struct pipe_sampler_state *); - -extern void -cell_bind_sampler_state(struct pipe_context *, unsigned, void *); - -extern void -cell_delete_sampler_state(struct pipe_context *, void *); - - -extern void * -cell_create_depth_stencil_alpha_state(struct pipe_context *, -                                const struct pipe_depth_stencil_alpha_state *); - -extern void -cell_bind_depth_stencil_alpha_state(struct pipe_context *, void *); - -extern void -cell_delete_depth_stencil_alpha_state(struct pipe_context *, void *); - - -void *cell_create_fs_state(struct pipe_context *, -                               const struct pipe_shader_state *); -void cell_bind_fs_state(struct pipe_context *, void *); -void cell_delete_fs_state(struct pipe_context *, void *); -void *cell_create_vs_state(struct pipe_context *, -                               const struct pipe_shader_state *); -void cell_bind_vs_state(struct pipe_context *, void *); -void cell_delete_vs_state(struct pipe_context *, void *); - - -void * -cell_create_rasterizer_state(struct pipe_context *, -                             const struct pipe_rasterizer_state *); -void cell_bind_rasterizer_state(struct pipe_context *, void *); -void cell_delete_rasterizer_state(struct pipe_context *, void *); - - -void cell_set_clip_state( struct pipe_context *, -                          const struct pipe_clip_state * ); - -void cell_set_constant_buffer(struct pipe_context *pipe, -                              uint shader, uint index, -                              const struct pipe_constant_buffer *buf); - -void cell_set_polygon_stipple( struct pipe_context *, -                               const struct pipe_poly_stipple * ); - -void -cell_set_sampler_texture(struct pipe_context *pipe, -                         unsigned sampler, -                         struct pipe_texture *texture); - -void cell_set_scissor_state( struct pipe_context *, -                             const struct pipe_scissor_state * ); - -void cell_set_texture_state( struct pipe_context *, -                             unsigned unit, struct pipe_texture * ); -  void cell_set_vertex_element(struct pipe_context *,                               unsigned index,                               const struct pipe_vertex_element *); @@ -106,10 +56,11 @@ void cell_set_vertex_buffer(struct pipe_context *,                              unsigned index,                              const struct pipe_vertex_buffer *); -void cell_set_viewport_state( struct pipe_context *, -                              const struct pipe_viewport_state * ); +void cell_update_derived( struct cell_context *softpipe ); -void cell_update_derived( struct cell_context *softpipe ); +void +cell_init_shader_functions(struct cell_context *cell); + +#endif /* CELL_STATE_H */ -#endif diff --git a/src/gallium/drivers/cell/ppu/cell_state_blend.c b/src/gallium/drivers/cell/ppu/cell_state_blend.c deleted file mode 100644 index b6d6d71f0c..0000000000 --- a/src/gallium/drivers/cell/ppu/cell_state_blend.c +++ /dev/null @@ -1,109 +0,0 @@ -/************************************************************************** - *  - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - *  - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - *  - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - *  - **************************************************************************/ - -/* Authors:  Keith Whitwell <keith@tungstengraphics.com> - */ - -#include "pipe/p_util.h" -#include "draw/draw_context.h" -#include "cell_context.h" -#include "cell_state.h" - - - -void * -cell_create_blend_state(struct pipe_context *pipe, -                        const struct pipe_blend_state *blend) -{ -   return mem_dup(blend, sizeof(*blend)); -} - - -void -cell_bind_blend_state(struct pipe_context *pipe, void *blend) -{ -   struct cell_context *cell = cell_context(pipe); - -   draw_flush(cell->draw); - -   cell->blend = (const struct pipe_blend_state *)blend; - -   cell->dirty |= CELL_NEW_BLEND; -} - - -void -cell_delete_blend_state(struct pipe_context *pipe, void *blend) -{ -   FREE(blend); -} - - -void -cell_set_blend_color(struct pipe_context *pipe, -                     const struct pipe_blend_color *blend_color) -{ -   struct cell_context *cell = cell_context(pipe); - -   draw_flush(cell->draw); - -   cell->blend_color = *blend_color; - -   cell->dirty |= CELL_NEW_BLEND; -} - - - - -void * -cell_create_depth_stencil_alpha_state(struct pipe_context *pipe, -                 const struct pipe_depth_stencil_alpha_state *depth_stencil) -{ -   return mem_dup(depth_stencil, sizeof(*depth_stencil)); -} - - -void -cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe, -                                    void *depth_stencil) -{ -   struct cell_context *cell = cell_context(pipe); - -   draw_flush(cell->draw); - -   cell->depth_stencil -      = (const struct pipe_depth_stencil_alpha_state *) depth_stencil; - -   cell->dirty |= CELL_NEW_DEPTH_STENCIL; -} - - -void -cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *depth) -{ -   FREE(depth); -} diff --git a/src/gallium/drivers/cell/ppu/cell_state_clip.c b/src/gallium/drivers/cell/ppu/cell_state_clip.c deleted file mode 100644 index 0482f87e88..0000000000 --- a/src/gallium/drivers/cell/ppu/cell_state_clip.c +++ /dev/null @@ -1,84 +0,0 @@ -/************************************************************************** - *  - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - *  - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - *  - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - *  - **************************************************************************/ - -/* Authors:  Keith Whitwell <keith@tungstengraphics.com> - */ - -#include "cell_context.h" -#include "cell_state.h" -#include "draw/draw_context.h" - - -void cell_set_clip_state( struct pipe_context *pipe, -			     const struct pipe_clip_state *clip ) -{ -   struct cell_context *cell = cell_context(pipe); - -   /* pass the clip state to the draw module */ -   draw_set_clip_state(cell->draw, clip); -} - - - -/* Called when driver state tracker notices changes to the viewport - * matrix: - */ -void cell_set_viewport_state( struct pipe_context *pipe, -                              const struct pipe_viewport_state *viewport ) -{ -   struct cell_context *cell = cell_context(pipe); - -   cell->viewport = *viewport; /* struct copy */ -   cell->dirty |= CELL_NEW_VIEWPORT; - -   /* pass the viewport info to the draw module */ -   draw_set_viewport_state(cell->draw, viewport); - -   /* Using tnl/ and vf/ modules is temporary while getting started. -    * Full pipe will have vertex shader, vertex fetch of its own. -    */ -} - - -void cell_set_scissor_state( struct pipe_context *pipe, -                             const struct pipe_scissor_state *scissor ) -{ -   struct cell_context *cell = cell_context(pipe); - -   memcpy( &cell->scissor, scissor, sizeof(*scissor) ); -   cell->dirty |= CELL_NEW_SCISSOR; -} - - -void cell_set_polygon_stipple( struct pipe_context *pipe, -                                   const struct pipe_poly_stipple *stipple ) -{ -   struct cell_context *cell = cell_context(pipe); - -   memcpy( &cell->poly_stipple, stipple, sizeof(*stipple) ); -   cell->dirty |= CELL_NEW_STIPPLE; -} diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index 5d2a786449..49c0d130c5 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -31,6 +31,8 @@  #include "cell_state_emit.h"  #include "cell_batch.h"  #include "cell_texture.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h"  static void @@ -100,4 +102,20 @@ cell_emit_state(struct cell_context *cell)        emit_state_cmd(cell, CELL_CMD_STATE_VERTEX_INFO,                       &cell->vertex_info, sizeof(struct vertex_info));     } +    +   if (cell->dirty & CELL_NEW_VS) { +      const struct draw_context *const draw = cell->draw; +      struct cell_shader_info info; + +      info.num_outputs = draw->num_vs_outputs; +      info.declarations = (uintptr_t) draw->machine.Declarations; +      info.num_declarations = draw->machine.NumDeclarations; +      info.instructions = (uintptr_t) draw->machine.Instructions; +      info.num_instructions = draw->machine.NumInstructions; +      info.immediates = (uintptr_t) draw->machine.Imms; +      info.num_immediates = draw->machine.ImmLimit / 4; + +      emit_state_cmd(cell, CELL_CMD_STATE_BIND_VS, +		     & info, sizeof(info)); +   }  } diff --git a/src/gallium/drivers/cell/ppu/cell_state_rasterizer.c b/src/gallium/drivers/cell/ppu/cell_state_rasterizer.c deleted file mode 100644 index 7eca5b5765..0000000000 --- a/src/gallium/drivers/cell/ppu/cell_state_rasterizer.c +++ /dev/null @@ -1,106 +0,0 @@ -/************************************************************************** - *  - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - *  - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - *  - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - *  - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - *  - **************************************************************************/ - -#include "pipe/p_defines.h" -#include "pipe/p_util.h" -#include "draw/draw_context.h" -#include "cell_context.h" -#include "cell_state.h" - - - -struct spu_rasterizer_state -{ -   unsigned flatshade:1; -#if 0 -   unsigned light_twoside:1; -   unsigned front_winding:2;  /**< PIPE_WINDING_x */ -   unsigned cull_mode:2;      /**< PIPE_WINDING_x */ -   unsigned fill_cw:2;        /**< PIPE_POLYGON_MODE_x */ -   unsigned fill_ccw:2;       /**< PIPE_POLYGON_MODE_x */ -   unsigned offset_cw:1; -   unsigned offset_ccw:1; -#endif -   unsigned scissor:1; -   unsigned poly_smooth:1; -   unsigned poly_stipple_enable:1; -   unsigned point_smooth:1; -#if 0 -   unsigned point_sprite:1; -   unsigned point_size_per_vertex:1; /**< size computed in vertex shader */ -#endif -   unsigned multisample:1;         /* XXX maybe more ms state in future */ -   unsigned line_smooth:1; -   unsigned line_stipple_enable:1; -   unsigned line_stipple_factor:8;  /**< [1..256] actually */ -   unsigned line_stipple_pattern:16; -#if 0 -   unsigned bypass_clipping:1; -#endif -   unsigned origin_lower_left:1;  /**< Is (0,0) the lower-left corner? */ - -   float line_width; -   float point_size;           /**< used when no per-vertex size */ -#if 0 -   float offset_units; -   float offset_scale; -   ubyte sprite_coord_mode[PIPE_MAX_SHADER_OUTPUTS]; /**< PIPE_SPRITE_COORD_ */ -#endif -}; - - - -void * -cell_create_rasterizer_state(struct pipe_context *pipe, -                             const struct pipe_rasterizer_state *setup) -{ -   struct pipe_rasterizer_state *state -      = MALLOC(sizeof(struct pipe_rasterizer_state)); -   memcpy(state, setup, sizeof(struct pipe_rasterizer_state)); -   return state; -} - - -void -cell_bind_rasterizer_state(struct pipe_context *pipe, void *setup) -{ -   struct cell_context *cell = cell_context(pipe); - -   /* pass-through to draw module */ -   draw_set_rasterizer_state(cell->draw, setup); - -   cell->rasterizer = (struct pipe_rasterizer_state *)setup; - -   cell->dirty |= CELL_NEW_RASTERIZER; -} - - -void -cell_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer) -{ -   FREE(rasterizer); -} diff --git a/src/gallium/drivers/cell/ppu/cell_state_fs.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c index b2ed699a5b..935501441b 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_fs.c +++ b/src/gallium/drivers/cell/ppu/cell_state_shader.c @@ -32,7 +32,7 @@  #include "draw/draw_context.h"  #if 0  #include "pipe/p_shader_tokens.h" -#include "llvm/gallivm.h" +#include "gallivm/gallivm.h"  #include "tgsi/util/tgsi_dump.h"  #include "tgsi/exec/tgsi_sse2.h"  #endif @@ -41,7 +41,7 @@  #include "cell_state.h" -void * +static void *  cell_create_fs_state(struct pipe_context *pipe,                       const struct pipe_shader_state *templ)  { @@ -80,7 +80,7 @@ cell_create_fs_state(struct pipe_context *pipe,  } -void +static void  cell_bind_fs_state(struct pipe_context *pipe, void *fs)  {     struct cell_context *cell = cell_context(pipe); @@ -91,7 +91,7 @@ cell_bind_fs_state(struct pipe_context *pipe, void *fs)  } -void +static void  cell_delete_fs_state(struct pipe_context *pipe, void *fs)  {     struct cell_fragment_shader_state *state = @@ -101,7 +101,7 @@ cell_delete_fs_state(struct pipe_context *pipe, void *fs)  } -void * +static void *  cell_create_vs_state(struct pipe_context *pipe,                       const struct pipe_shader_state *templ)  { @@ -124,7 +124,7 @@ cell_create_vs_state(struct pipe_context *pipe,  } -void +static void  cell_bind_vs_state(struct pipe_context *pipe, void *vs)  {     struct cell_context *cell = cell_context(pipe); @@ -137,7 +137,7 @@ cell_bind_vs_state(struct pipe_context *pipe, void *vs)  } -void +static void  cell_delete_vs_state(struct pipe_context *pipe, void *vs)  {     struct cell_context *cell = cell_context(pipe); @@ -150,7 +150,7 @@ cell_delete_vs_state(struct pipe_context *pipe, void *vs)  } -void +static void  cell_set_constant_buffer(struct pipe_context *pipe,                           uint shader, uint index,                           const struct pipe_constant_buffer *buf) @@ -169,3 +169,18 @@ cell_set_constant_buffer(struct pipe_context *pipe,     cell->dirty |= CELL_NEW_CONSTANTS;  } + + +void +cell_init_shader_functions(struct cell_context *cell) +{ +   cell->pipe.create_fs_state = cell_create_fs_state; +   cell->pipe.bind_fs_state   = cell_bind_fs_state; +   cell->pipe.delete_fs_state = cell_delete_fs_state; + +   cell->pipe.create_vs_state = cell_create_vs_state; +   cell->pipe.bind_vs_state   = cell_bind_vs_state; +   cell->pipe.delete_vs_state = cell_delete_vs_state; + +   cell->pipe.set_constant_buffer = cell_set_constant_buffer; +} diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index c8ef36002f..0edefa5f05 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -79,14 +79,16 @@ cell_texture_layout(struct cell_texture * spt)  } -struct pipe_texture * -cell_texture_create(struct pipe_context *pipe, const struct pipe_texture *templat) +static struct pipe_texture * +cell_texture_create(struct pipe_context *pipe, +                    const struct pipe_texture *templat)  {     struct cell_texture *spt = CALLOC_STRUCT(cell_texture);     if (!spt)        return NULL;     spt->base = *templat; +   spt->base.refcount = 1;     cell_texture_layout(spt); @@ -103,7 +105,7 @@ cell_texture_create(struct pipe_context *pipe, const struct pipe_texture *templa  } -void +static void  cell_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)  {     if (!*pt) @@ -128,10 +130,18 @@ cell_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)  } +static void +cell_texture_update(struct pipe_context *pipe, struct pipe_texture *texture) +{ +   /* XXX TO DO:  re-tile the texture data ... */ + +} + +  /**   * Called via pipe->get_tex_surface()   */ -struct pipe_surface * +static struct pipe_surface *  cell_get_tex_surface(struct pipe_context *pipe,                           struct pipe_texture *pt,                           unsigned face, unsigned level, unsigned zslice) @@ -250,3 +260,13 @@ cell_update_texture_mapping(struct cell_context *cell)     cell->tex_map = pipe_surface_map(cell->tex_surf);  #endif  } + + +void +cell_init_texture_functions(struct cell_context *cell) +{ +   cell->pipe.texture_create = cell_texture_create; +   cell->pipe.texture_release = cell_texture_release; +   cell->pipe.texture_update = cell_texture_update; +   cell->pipe.get_tex_surface = cell_get_tex_surface; +} diff --git a/src/gallium/drivers/cell/ppu/cell_texture.h b/src/gallium/drivers/cell/ppu/cell_texture.h index 0264fed88e..824fb3e20f 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.h +++ b/src/gallium/drivers/cell/ppu/cell_texture.h @@ -29,7 +29,7 @@  #define CELL_TEXTURE_H -struct pipe_context; +struct cell_context;  struct pipe_texture; @@ -60,21 +60,12 @@ cell_texture(struct pipe_texture *pt) -extern struct pipe_texture * -cell_texture_create(struct pipe_context *pipe, -                    const struct pipe_texture *templat); -  extern void -cell_texture_release(struct pipe_context *pipe, struct pipe_texture **pt); - -extern struct pipe_surface * -cell_get_tex_surface(struct pipe_context *pipe, -                     struct pipe_texture *pt, -                     unsigned face, unsigned level, unsigned zslice); +cell_update_texture_mapping(struct cell_context *cell);  extern void -cell_update_texture_mapping(struct cell_context *cell); +cell_init_texture_functions(struct cell_context *cell); -#endif /* CELL_TEXTURE */ +#endif /* CELL_TEXTURE_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c b/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c index f10689a959..9cf74bab47 100644 --- a/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c +++ b/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c @@ -31,7 +31,7 @@  #include "../auxiliary/draw/draw_private.h"  #include "cell_context.h" -#include "ppc/rtasm/spe_asm.h" +#include "rtasm/rtasm_ppc_spe.h"  typedef uint64_t register_mask; diff --git a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c index 6a1d3bc20a..f7ef72e5a2 100644 --- a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c +++ b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c @@ -35,6 +35,7 @@  #include "cell_context.h"  #include "cell_draw_arrays.h" +#include "cell_flush.h"  #include "cell_spu.h"  #include "cell_batch.h" @@ -54,6 +55,7 @@ cell_vertex_shader_queue_flush(struct draw_context *draw)     struct cell_command_vs *const vs = &cell_global.command[0].vs;     uint64_t *batch;     struct cell_array_info *array_info; +   struct cell_shader_info *shader_info;     unsigned i, j;     struct cell_attribute_fetch_code *cf; @@ -100,17 +102,17 @@ cell_vertex_shader_queue_flush(struct draw_context *draw)     (void) memcpy(&batch[1], &draw->viewport,                   sizeof(struct pipe_viewport_state)); +   { +      uint64_t uniforms = (uintptr_t) draw->user.constants; + +      batch = cell_batch_alloc(cell, 2 *sizeof(batch[0])); +      batch[0] = CELL_CMD_STATE_UNIFORMS; +      batch[1] = uniforms; +   } +     cell_batch_flush(cell);     vs->opcode = CELL_CMD_VS_EXECUTE; -   vs->shader.num_outputs = draw->num_vs_outputs; -   vs->shader.declarations = (uintptr_t) draw->machine.Declarations; -   vs->shader.num_declarations = draw->machine.NumDeclarations; -   vs->shader.instructions = (uintptr_t) draw->machine.Instructions; -   vs->shader.num_instructions = draw->machine.NumInstructions; -   vs->shader.uniforms = (uintptr_t) draw->user.constants; -   vs->shader.immediates = (uintptr_t) draw->machine.Imms; -   vs->shader.num_immediates = draw->machine.ImmLimit / 4;     vs->nr_attrs = draw->vertex_fetch.nr_attrs;     (void) memcpy(vs->plane, draw->plane, sizeof(draw->plane)); diff --git a/src/gallium/drivers/cell/spu/Makefile b/src/gallium/drivers/cell/spu/Makefile index 30ef2450ec..c071de1900 100644 --- a/src/gallium/drivers/cell/spu/Makefile +++ b/src/gallium/drivers/cell/spu/Makefile @@ -18,6 +18,7 @@ PROG_SPU_EMBED_O = $(PROG)_spu-embed.o  SOURCES = \  	spu_main.c \  	spu_blend.c \ +	spu_dcache.c \  	spu_render.c \  	spu_texture.c \  	spu_tile.c \ diff --git a/src/gallium/drivers/cell/spu/spu_dcache.c b/src/gallium/drivers/cell/spu/spu_dcache.c new file mode 100644 index 0000000000..698a5790bb --- /dev/null +++ b/src/gallium/drivers/cell/spu/spu_dcache.c @@ -0,0 +1,111 @@ +/* + * (C) Copyright IBM Corporation 2008 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL + * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "cell/common.h" +#include "spu_main.h" +#include "spu_dcache.h" + +#define CACHELINE_LOG2SIZE    7 +#define LINE_SIZE             (1U << 7) +#define ALIGN_MASK            (~(LINE_SIZE - 1)) + +#define CACHE_NAME            data +#define CACHED_TYPE           qword +#define CACHE_TYPE            CACHE_TYPE_RO +#define CACHE_SET_TAGID(set)  TAG_VERTEX_BUFFER +#define CACHE_LOG2NNWAY       2 +#define CACHE_LOG2NSETS       6 +#include <cache-api.h> + +/* Yes folks, this is ugly. + */ +#undef CACHE_NWAY +#undef CACHE_NSETS +#define CACHE_NAME            data +#define CACHE_NWAY            4 +#define CACHE_NSETS           (1U << 6) + + +/** + * Fetch between arbitrary number of bytes from an unaligned address + */ +void +spu_dcache_fetch_unaligned(qword *dst, unsigned ea, unsigned size) +{ +   const int shift = ea & 0x0f; +   const unsigned aligned_start_ea = ea & ~0x0f; +   const unsigned aligned_end_ea = ROUNDUP16(ea + size); +   const unsigned num_entries = (aligned_end_ea - aligned_start_ea) / 16; +   unsigned i; + + +   if (shift == 0) { +      /* Data is already aligned.  Fetch directly into the destination buffer. +       */ +      for (i = 0; i < num_entries; i++) { +         dst[i] = cache_rd(data, ea + (i * 16)); +      } +   } else { +      qword tmp[2] ALIGN16_ATTRIB; + + +      tmp[0] = cache_rd(data, (ea & ~0x0f)); +      for (i = 0; i < (num_entries & ~1); i++) { +         const unsigned curr = i & 1; +         const unsigned next = curr ^ 1; + +         tmp[next] = cache_rd(data, (ea & ~0x0f) + (next * 16)); + +         dst[i] = si_or((qword) spu_slqwbyte(tmp[curr], shift), +                        (qword) spu_rlmaskqwbyte(tmp[next], shift - 16)); +      } + +      if (i < num_entries) { +         dst[i] = si_or((qword) spu_slqwbyte(tmp[(i & 1)], shift), +                        si_il(0)); +      } +   } +} + + +/** + * Notify the cache that a range of main memory may have been modified + */ +void +spu_dcache_mark_dirty(unsigned ea, unsigned size) +{ +   unsigned i; +   const unsigned aligned_start = (ea & ALIGN_MASK); +   const unsigned aligned_end = (ea + size + (LINE_SIZE - 1))  +       & ALIGN_MASK; + + +   for (i = 0; i < (CACHE_NWAY * CACHE_NSETS); i++) { +      const unsigned entry = __cache_dir[i]; +      const unsigned addr = entry & ~0x0f; + +      __cache_dir[i] = ((addr >= aligned_start) && (addr < aligned_end)) +          ? (entry & ~CACHELINE_VALID) : entry; +   } +} diff --git a/src/gallium/drivers/cell/spu/spu_dcache.h b/src/gallium/drivers/cell/spu/spu_dcache.h new file mode 100644 index 0000000000..7a06b8c25a --- /dev/null +++ b/src/gallium/drivers/cell/spu/spu_dcache.h @@ -0,0 +1,34 @@ +/* + * (C) Copyright IBM Corporation 2008 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL + * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPU_DCACHE_H +#define SPU_DCACHE_H + +extern void +spu_dcache_fetch_unaligned(qword *dst, unsigned ea, unsigned size); + +extern void +spu_dcache_mark_dirty(unsigned ea, unsigned size); + +#endif /* SPU_DCACHE_H */ diff --git a/src/gallium/drivers/cell/spu/spu_exec.c b/src/gallium/drivers/cell/spu/spu_exec.c index 109540b1f7..cf81bee8fd 100644 --- a/src/gallium/drivers/cell/spu/spu_exec.c +++ b/src/gallium/drivers/cell/spu/spu_exec.c @@ -72,6 +72,8 @@  #include "spu_exec.h"  #include "spu_main.h"  #include "spu_vertex_shader.h" +#include "spu_dcache.h" +#include "cell/common.h"  #define TILE_TOP_LEFT     0  #define TILE_TOP_RIGHT    1 @@ -146,17 +148,13 @@ spu_exec_machine_init(struct spu_exec_machine *mach,                        struct spu_sampler *samplers,                        unsigned processor)  { -   qword zero; -   qword not_zero; -   uint i; +   const qword zero = si_il(0); +   const qword not_zero = si_il(~0);     mach->Samplers = samplers;     mach->Processor = processor;     mach->Addrs = &mach->Temps[TGSI_EXEC_NUM_TEMPS]; -   zero = si_xor(zero, zero); -   not_zero = si_xori(zero, 0xff); -     /* Setup constants. */     mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].q = zero;     mach->Temps[TEMP_FF_I].xyzw[TEMP_FF_C].q = not_zero; @@ -356,19 +354,17 @@ fetch_src_file_channel(     case TGSI_EXTSWIZZLE_W:        switch( file ) {        case TGSI_FILE_CONSTANT: { -         unsigned char buffer[32] ALIGN16_ATTRIB;           unsigned i;           for (i = 0; i < 4; i++) {              const float *ptr = mach->Consts[index->i[i]]; -            const uint64_t addr = (uint64_t)(uintptr_t) ptr; -            const unsigned size = ((addr & 0x0f) == 0) ? 16 : 32; +            float tmp[4]; -            mfc_get(buffer, addr & ~0x0f, size, TAG_VERTEX_BUFFER, 0, 0); -            wait_on_mask(1 << TAG_VERTEX_BUFFER); +            spu_dcache_fetch_unaligned((qword *) tmp, +                                       (uintptr_t)(ptr + swizzle), +                                       sizeof(float)); -            (void) memcpy(& chan->f[i], &buffer[(addr & 0x0f)  -                + (sizeof(float) * swizzle)], sizeof(float)); +            chan->f[i] = tmp[0];           }           break;        } @@ -1903,32 +1899,28 @@ spu_exec_machine_run( struct spu_exec_machine *mach )     /* execute declarations (interpolants) */     if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) {        for (i = 0; i < mach->NumDeclarations; i++) { -	 uint8_t buffer[sizeof(struct tgsi_full_declaration) + 32] ALIGN16_ATTRIB; -	 struct tgsi_full_declaration decl; -	 unsigned long decl_addr = (unsigned long) (mach->Declarations+i); -	 unsigned size = ((sizeof(decl) + (decl_addr & 0x0f) + 0x0f) & ~0x0f); +         union { +            struct tgsi_full_declaration decl; +            qword buffer[ROUNDUP16(sizeof(struct tgsi_full_declaration)) / 16]; +         } d ALIGN16_ATTRIB; +         unsigned ea = (unsigned) (mach->Declarations + pc); -	 mfc_get(buffer, decl_addr & ~0x0f, size, TAG_INSTRUCTION_FETCH, 0, 0); -	 wait_on_mask(1 << TAG_INSTRUCTION_FETCH); +         spu_dcache_fetch_unaligned(d.buffer, ea, sizeof(d.decl)); -	 memcpy(& decl, buffer + (decl_addr & 0x0f), sizeof(decl)); -	 exec_declaration( mach, &decl ); +         exec_declaration( mach, &d.decl );        }     }     /* execute instructions, until pc is set to -1 */     while (pc != -1) { -      uint8_t buffer[sizeof(struct tgsi_full_instruction) + 32] ALIGN16_ATTRIB; -      struct tgsi_full_instruction inst; -      unsigned long inst_addr = (unsigned long) (mach->Instructions + pc); -      unsigned size = ((sizeof(inst) + (inst_addr & 0x0f) + 0x0f) & ~0x0f); - -      assert(pc < mach->NumInstructions); -      mfc_get(buffer, inst_addr & ~0x0f, size, TAG_INSTRUCTION_FETCH, 0, 0); -      wait_on_mask(1 << TAG_INSTRUCTION_FETCH); +      union { +         struct tgsi_full_instruction inst; +         qword buffer[ROUNDUP16(sizeof(struct tgsi_full_instruction)) / 16]; +      } i ALIGN16_ATTRIB; +      unsigned ea = (unsigned) (mach->Instructions + pc); -      memcpy(& inst, buffer + (inst_addr & 0x0f), sizeof(inst)); -      exec_instruction( mach, & inst, &pc ); +      spu_dcache_fetch_unaligned(i.buffer, ea, sizeof(i.inst)); +      exec_instruction( mach, & i.inst, &pc );     }  #if 0 diff --git a/src/gallium/drivers/cell/spu/spu_main.c b/src/gallium/drivers/cell/spu/spu_main.c index fcbf0f841e..1136dba62d 100644 --- a/src/gallium/drivers/cell/spu/spu_main.c +++ b/src/gallium/drivers/cell/spu/spu_main.c @@ -433,10 +433,19 @@ cmd_batch(uint opcode)                         sizeof(struct pipe_viewport_state));           pos += (1 + ROUNDUP8(sizeof(struct pipe_viewport_state)) / 8);           break; +      case CELL_CMD_STATE_UNIFORMS: +         draw.constants = (float (*)[4]) (uintptr_t) buffer[pos + 1]; +         pos += 2; +         break;        case CELL_CMD_STATE_VS_ARRAY_INFO:           cmd_state_vs_array_info((struct cell_array_info *) &buffer[pos+1]);           pos += (1 + ROUNDUP8(sizeof(struct cell_array_info)) / 8);           break; +      case CELL_CMD_STATE_BIND_VS: +         spu_bind_vertex_shader(&draw, +                                (struct cell_shader_info *) &buffer[pos+1]); +         pos += (1 + ROUNDUP8(sizeof(struct cell_shader_info)) / 8); +         break;        case CELL_CMD_STATE_ATTRIB_FETCH: {           struct cell_attribute_fetch_code *code =               (struct cell_attribute_fetch_code *) &buffer[pos+1]; @@ -453,6 +462,14 @@ cmd_batch(uint opcode)           pos += (1 + ROUNDUP8(sizeof(struct cell_attribute_fetch_code)) / 8);           break;        } +      case CELL_CMD_FLUSH_BUFFER_RANGE: { +	 struct cell_buffer_range *br = (struct cell_buffer_range *) +	     &buffer[pos+1]; + +	 spu_dcache_mark_dirty((unsigned) br->base, br->size); +         pos += (1 + ROUNDUP8(sizeof(struct cell_buffer_range)) / 8); +	 break; +      }        default:           printf("SPU %u: bad opcode: 0x%llx\n", spu.init.id, buffer[pos]);           ASSERT(0); diff --git a/src/gallium/drivers/cell/spu/spu_vertex_fetch.c b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c index 55c6c28717..f7e4e653e3 100644 --- a/src/gallium/drivers/cell/spu/spu_vertex_fetch.c +++ b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c @@ -40,31 +40,13 @@  #include "spu_exec.h"  #include "spu_vertex_shader.h"  #include "spu_main.h" - -#define CACHE_NAME            attribute -#define CACHED_TYPE           qword -#define CACHE_TYPE            CACHE_TYPE_RO -#define CACHE_SET_TAGID(set)  TAG_VERTEX_BUFFER -#define CACHE_LOG2NNWAY       2 -#define CACHE_LOG2NSETS       6 -#include <cache-api.h> - -/* Yes folks, this is ugly. - */ -#undef CACHE_NWAY -#undef CACHE_NSETS -#define CACHE_NAME            attribute -#define CACHE_NWAY            4 -#define CACHE_NSETS           (1U << 6) - - -#define DRAW_DBG 0 +#include "spu_dcache.h"  typedef void (*spu_fetch_func)(qword *out, const qword *in,  			       const qword *shuffle_data); -static const qword fetch_shuffle_data[] = { +static const qword fetch_shuffle_data[5] ALIGN16_ATTRIB = {     /* Shuffle used by CVT_64_FLOAT      */     { @@ -103,44 +85,6 @@ static const qword fetch_shuffle_data[] = {  /** - * Fetch between 1 and 32 bytes from an unaligned address - */ -static INLINE void -fetch_unaligned(qword *dst, unsigned ea, unsigned size) -{ -   qword tmp[4]; -   const int shift = ea & 0x0f; -   const unsigned aligned_start_ea = ea & ~0x0f; -   const unsigned aligned_end_ea = (ea + size) & ~0x0f; -   const unsigned num_entries = ((aligned_end_ea - aligned_start_ea) / 16) + 1; -   unsigned i; - - -   if (shift == 0) { -      /* Data is already aligned.  Fetch directly into the destination buffer. -       */ -      for (i = 0; i < num_entries; i++) { -	 dst[i] = cache_rd(attribute, (ea & ~0x0f) + (i * 16)); -      } -   } else { -      /* Fetch data from the cache to the local buffer. -       */ -      for (i = 0; i < num_entries; i++) { -	 tmp[i] = cache_rd(attribute, (ea & ~0x0f) + (i * 16)); -      } - - -      /* Fix the alignment of the data and write to the destination buffer. -       */ -      for (i = 0; i < ((size + 15) / 16); i++) { -	 dst[i] = si_or((qword) spu_slqwbyte(tmp[i], shift), -			(qword) spu_rlmaskqwbyte(tmp[i + 1], shift - 16)); -      } -   } -} - - -/**   * Fetch vertex attributes for 'count' vertices.   */  static void generic_vertex_fetch(struct spu_vs_context *draw, @@ -169,7 +113,7 @@ static void generic_vertex_fetch(struct spu_vs_context *draw,        unsigned idx;        const unsigned bytes_per_entry = draw->vertex_fetch.size[attr];        const unsigned quads_per_entry = (bytes_per_entry + 15) / 16; -      qword in[2 * 4]; +      qword in[2 * 4] ALIGN16_ATTRIB;        /* Fetch four attributes for four vertices.   @@ -182,7 +126,7 @@ static void generic_vertex_fetch(struct spu_vs_context *draw,           printf("SPU: fetching = 0x%llx\n", addr);  #endif -         fetch_unaligned(& in[idx], addr, bytes_per_entry); +         spu_dcache_fetch_unaligned(& in[idx], addr, bytes_per_entry);           idx += quads_per_entry;        } @@ -200,15 +144,5 @@ static void generic_vertex_fetch(struct spu_vs_context *draw,  void spu_update_vertex_fetch( struct spu_vs_context *draw )  { -   unsigned i; - -    -   /* Invalidate the vertex cache. -    */ -   for (i = 0; i < (CACHE_NWAY * CACHE_NSETS); i++) { -      CACHELINE_CLEARVALID(i); -   } - -     draw->vertex_fetch.fetch_func = generic_vertex_fetch;  } diff --git a/src/gallium/drivers/cell/spu/spu_vertex_shader.c b/src/gallium/drivers/cell/spu/spu_vertex_shader.c index 3f5bf41aa2..8363efeeb6 100644 --- a/src/gallium/drivers/cell/spu/spu_vertex_shader.c +++ b/src/gallium/drivers/cell/spu/spu_vertex_shader.c @@ -165,63 +165,55 @@ run_vertex_program(struct spu_vs_context *draw,  } -static void -spu_bind_vertex_shader(struct spu_vs_context *draw, -		       void *uniforms, -		       void *planes, -		       unsigned nr_planes, -		       unsigned num_outputs -		       ) -{ -   draw->constants = (float (*)[4]) uniforms; - -   (void) memcpy(draw->plane, planes, sizeof(float) * 4 * nr_planes); -   draw->nr_planes = nr_planes; -   draw->num_vs_outputs = num_outputs; - -   /* specify the shader to interpret/execute */ -   spu_exec_machine_init(&draw->machine, -			 PIPE_MAX_SAMPLERS, -			 NULL /*samplers*/, -			 PIPE_SHADER_VERTEX); -} - -  unsigned char immediates[(sizeof(float) * 4 * TGSI_EXEC_NUM_IMMEDIATES) + 32]      ALIGN16_ATTRIB; +  void -spu_execute_vertex_shader(struct spu_vs_context *draw, -                          const struct cell_command_vs *vs) +spu_bind_vertex_shader(struct spu_vs_context *draw, +		       struct cell_shader_info *vs)  { -   unsigned i; - -   const uint64_t immediate_addr = vs->shader.immediates; +   const unsigned immediate_addr = vs->immediates;     const unsigned immediate_size =  -       ROUNDUP16((sizeof(float) * 4 * vs->shader.num_immediates) -                 + (immediate_addr & 0x0f)); +       ROUNDUP16((sizeof(float) * 4 * vs->num_immediates) +		 + (immediate_addr & 0x0f)); +      mfc_get(immediates, immediate_addr & ~0x0f, immediate_size,             TAG_VERTEX_BUFFER, 0, 0);     draw->machine.Instructions = (struct tgsi_full_instruction *) -       vs->shader.instructions; -   draw->machine.NumInstructions = vs->shader.num_instructions; +       vs->instructions; +   draw->machine.NumInstructions = vs->num_instructions;     draw->machine.Declarations = (struct tgsi_full_declaration *) -       vs->shader.declarations; -   draw->machine.NumDeclarations = vs->shader.num_declarations; +       vs->declarations; +   draw->machine.NumDeclarations = vs->num_declarations; -   draw->vertex_fetch.nr_attrs = vs->nr_attrs; +   draw->num_vs_outputs = vs->num_outputs; + +   /* specify the shader to interpret/execute */ +   spu_exec_machine_init(&draw->machine, +			 PIPE_MAX_SAMPLERS, +			 NULL /*samplers*/, +			 PIPE_SHADER_VERTEX);     wait_on_mask(1 << TAG_VERTEX_BUFFER);     (void) memcpy(& draw->machine.Imms, &immediates[immediate_addr & 0x0f], -                 sizeof(float) * 4 * vs->shader.num_immediates); +                 sizeof(float) * 4 * vs->num_immediates); +} -   spu_bind_vertex_shader(draw, vs->shader.uniforms, -                          vs->plane, vs->nr_planes, -                          vs->shader.num_outputs); + +void +spu_execute_vertex_shader(struct spu_vs_context *draw, +                          const struct cell_command_vs *vs) +{ +   unsigned i; + +   (void) memcpy(draw->plane, vs->plane, sizeof(float) * 4 * vs->nr_planes); +   draw->nr_planes = vs->nr_planes; +   draw->vertex_fetch.nr_attrs = vs->nr_attrs;     for (i = 0; i < vs->num_elts; i += 4) {        const unsigned batch_size = MIN2(vs->num_elts - i, 4); diff --git a/src/gallium/drivers/cell/spu/spu_vertex_shader.h b/src/gallium/drivers/cell/spu/spu_vertex_shader.h index 0fb0bc28d0..54a4b8d9b9 100644 --- a/src/gallium/drivers/cell/spu/spu_vertex_shader.h +++ b/src/gallium/drivers/cell/spu/spu_vertex_shader.h @@ -1,6 +1,7 @@  #ifndef SPU_VERTEX_SHADER_H  #define SPU_VERTEX_SHADER_H +#include "cell/common.h"  #include "pipe/p_format.h"  #include "spu_exec.h" @@ -55,6 +56,10 @@ static INLINE void spu_vertex_fetch(struct spu_vs_context *draw,  struct cell_command_vs;  extern void +spu_bind_vertex_shader(struct spu_vs_context *draw, +		       struct cell_shader_info *vs); + +extern void  spu_execute_vertex_shader(struct spu_vs_context *draw,  			  const struct cell_command_vs *vs); diff --git a/src/gallium/drivers/failover/Makefile b/src/gallium/drivers/failover/Makefile index 14389bd055..f08b8df07a 100644 --- a/src/gallium/drivers/failover/Makefile +++ b/src/gallium/drivers/failover/Makefile @@ -1,20 +1,13 @@ -  TOP = ../../../..  include $(TOP)/configs/current  LIBNAME = failover -DRIVER_SOURCES = \ +C_SOURCES = \  	fo_state.c \  	fo_state_emit.c \  	fo_context.c  -C_SOURCES = \ -	$(COMMON_SOURCES) \ -	$(DRIVER_SOURCES) - -ASM_SOURCES =  -  include ../../Makefile.template  symlinks: diff --git a/src/gallium/drivers/failover/SConscript b/src/gallium/drivers/failover/SConscript new file mode 100644 index 0000000000..f8e9b1b491 --- /dev/null +++ b/src/gallium/drivers/failover/SConscript @@ -0,0 +1,13 @@ +Import('*') + +env = env.Clone() + +failover = env.ConvenienceLibrary( +	target = 'failover', +	source = [ +		'fo_state.c', +		'fo_state_emit.c', +		'fo_context.c', +	]) + +Export('failover') diff --git a/src/gallium/drivers/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c index 7ce4a7df17..156f7399b0 100644 --- a/src/gallium/drivers/failover/fo_context.c +++ b/src/gallium/drivers/failover/fo_context.c @@ -137,15 +137,14 @@ struct pipe_context *failover_create( struct pipe_context *hw,     failover_init_state_functions( failover ); -#if 0 -   failover->pipe.surface_alloc = hw->surface_alloc; -#endif -   failover->pipe.get_tex_surface = hw->get_tex_surface; -     failover->pipe.surface_copy = hw->surface_copy;     failover->pipe.surface_fill = hw->surface_fill; +     failover->pipe.texture_create = hw->texture_create;     failover->pipe.texture_release = hw->texture_release; +   failover->pipe.texture_update = hw->texture_update; +   failover->pipe.get_tex_surface = hw->get_tex_surface; +     failover->pipe.flush = hw->flush;     failover->dirty = 0; diff --git a/src/gallium/drivers/i915simple/Makefile b/src/gallium/drivers/i915simple/Makefile index ee22ba86f9..2a75f5d57c 100644 --- a/src/gallium/drivers/i915simple/Makefile +++ b/src/gallium/drivers/i915simple/Makefile @@ -1,10 +1,9 @@ -  TOP = ../../../..  include $(TOP)/configs/current  LIBNAME = i915simple -DRIVER_SOURCES = \ +C_SOURCES = \  	i915_blit.c \  	i915_clear.c \  	i915_flush.c \ @@ -26,12 +25,6 @@ DRIVER_SOURCES = \  	i915_fpc_translate.c \  	i915_surface.c  -C_SOURCES = \ -	$(COMMON_SOURCES) \ -	$(DRIVER_SOURCES) - -ASM_SOURCES =  -  include ../../Makefile.template  symlinks: diff --git a/src/gallium/drivers/i915simple/i915_context.c b/src/gallium/drivers/i915simple/i915_context.c index 7f71f8fd4f..acfa349439 100644 --- a/src/gallium/drivers/i915simple/i915_context.c +++ b/src/gallium/drivers/i915simple/i915_context.c @@ -296,12 +296,11 @@ struct pipe_context *i915_create( struct pipe_winsys *pipe_winsys,     i915_init_state_functions(i915);     i915_init_flush_functions(i915);     i915_init_string_functions(i915); +   i915_init_texture_functions(i915);     i915->pci_id = pci_id;     i915->flags.is_i945 = is_i945; -   i915->pipe.texture_create = i915_texture_create; -   i915->pipe.texture_release = i915_texture_release;     i915->dirty = ~0;     i915->hardware_dirty = ~0; diff --git a/src/gallium/drivers/i915simple/i915_debug.c b/src/gallium/drivers/i915simple/i915_debug.c index 94db44e1aa..78102dbac2 100644 --- a/src/gallium/drivers/i915simple/i915_debug.c +++ b/src/gallium/drivers/i915simple/i915_debug.c @@ -25,8 +25,6 @@   *    **************************************************************************/ -//#include "imports.h" -  #include "i915_reg.h"  #include "i915_context.h"  #include "i915_winsys.h" diff --git a/src/gallium/drivers/i915simple/i915_state.c b/src/gallium/drivers/i915simple/i915_state.c index 294e6fad03..e055eed7e0 100644 --- a/src/gallium/drivers/i915simple/i915_state.c +++ b/src/gallium/drivers/i915simple/i915_state.c @@ -32,6 +32,7 @@  #include "draw/draw_context.h"  #include "pipe/p_winsys.h"  #include "pipe/p_util.h" +#include "pipe/p_inlines.h"  #include "i915_context.h"  #include "i915_reg.h" @@ -505,7 +506,9 @@ static void i915_set_sampler_texture(struct pipe_context *pipe,  {     struct i915_context *i915 = i915_context(pipe); -   i915->texture[sampler] = (struct i915_texture*)texture;  /* ptr, not struct */ +   pipe_texture_reference(pipe, +                          (struct pipe_texture **) &i915->texture[sampler], +                          texture);     i915->dirty |= I915_NEW_TEXTURE;  } diff --git a/src/gallium/drivers/i915simple/i915_state_immediate.c b/src/gallium/drivers/i915simple/i915_state_immediate.c index 07031fc6c5..dfbbcab624 100644 --- a/src/gallium/drivers/i915simple/i915_state_immediate.c +++ b/src/gallium/drivers/i915simple/i915_state_immediate.c @@ -33,7 +33,7 @@  #include "i915_context.h"  #include "i915_state.h"  #include "i915_reg.h" -#include "p_util.h" +#include "pipe/p_util.h"  /* All state expressable with the LOAD_STATE_IMMEDIATE_1 packet. diff --git a/src/gallium/drivers/i915simple/i915_state_inlines.h b/src/gallium/drivers/i915simple/i915_state_inlines.h index 0934ac79a4..378de8f9c4 100644 --- a/src/gallium/drivers/i915simple/i915_state_inlines.h +++ b/src/gallium/drivers/i915simple/i915_state_inlines.h @@ -28,8 +28,8 @@  #ifndef I915_STATE_INLINES_H  #define I915_STATE_INLINES_H -#include "p_compiler.h" -#include "p_defines.h" +#include "pipe/p_compiler.h" +#include "pipe/p_defines.h"  #include "i915_reg.h" diff --git a/src/gallium/drivers/i915simple/i915_surface.c b/src/gallium/drivers/i915simple/i915_surface.c index 17fd27895a..f4fbedbe9b 100644 --- a/src/gallium/drivers/i915simple/i915_surface.c +++ b/src/gallium/drivers/i915simple/i915_surface.c @@ -36,48 +36,6 @@  #include "util/p_tile.h" -/* - * XXX note: same as code in sp_surface.c - */ -static struct pipe_surface * -i915_get_tex_surface(struct pipe_context *pipe, -                     struct pipe_texture *pt, -                     unsigned face, unsigned level, unsigned zslice) -{ -   struct i915_texture *tex = (struct i915_texture *)pt; -   struct pipe_surface *ps; -   unsigned offset;  /* in bytes */ - -   offset = tex->level_offset[level]; - -   if (pt->target == PIPE_TEXTURE_CUBE) { -      offset += tex->image_offset[level][face] * pt->cpp; -   } -   else if (pt->target == PIPE_TEXTURE_3D) { -      offset += tex->image_offset[level][zslice] * pt->cpp; -   } -   else { -      assert(face == 0); -      assert(zslice == 0); -   } - -   ps = pipe->winsys->surface_alloc(pipe->winsys); -   if (ps) { -      assert(ps->refcount); -      assert(ps->winsys); -      pipe_buffer_reference(pipe->winsys, &ps->buffer, tex->buffer); -      ps->format = pt->format; -      ps->cpp = pt->cpp; -      ps->width = pt->width[level]; -      ps->height = pt->height[level]; -      ps->pitch = tex->pitch; -      ps->offset = offset; -   } -   return ps; -} - - -  /* Assumes all values are within bounds -- no checking at this level -   * do it higher up if required.   */ @@ -115,6 +73,7 @@ i915_surface_copy(struct pipe_context *pipe,     }  } +  /* Fill a rectangular sub-region.  Need better logic about when to   * push buffers into AGP - will currently do so whenever possible.   */ @@ -184,8 +143,6 @@ i915_surface_fill(struct pipe_context *pipe,  void  i915_init_surface_functions(struct i915_context *i915)  { -   i915->pipe.get_tex_surface = i915_get_tex_surface; -     i915->pipe.surface_copy = i915_surface_copy;     i915->pipe.surface_fill = i915_surface_fill;  } diff --git a/src/gallium/drivers/i915simple/i915_texture.c b/src/gallium/drivers/i915simple/i915_texture.c index 6d37ae3d74..1b415a94d4 100644 --- a/src/gallium/drivers/i915simple/i915_texture.c +++ b/src/gallium/drivers/i915simple/i915_texture.c @@ -478,7 +478,7 @@ i945_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)  } -struct pipe_texture * +static struct pipe_texture *  i915_texture_create(struct pipe_context *pipe,                      const struct pipe_texture *templat)  { @@ -488,6 +488,7 @@ i915_texture_create(struct pipe_context *pipe,        struct i915_context *i915 = i915_context(pipe);        tex->base = *templat; +      tex->base.refcount = 1;        if (i915->flags.is_i945 ? i945_miptree_layout(pipe, tex) :  	  i915_miptree_layout(pipe, tex)) @@ -506,7 +507,7 @@ i915_texture_create(struct pipe_context *pipe,  } -void +static void  i915_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)  {     if (!*pt) @@ -534,3 +535,62 @@ i915_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)     }     *pt = NULL;  } + + +static void +i915_texture_update(struct pipe_context *pipe, struct pipe_texture *texture) +{ +   /* no-op? */ +} + + +/* + * XXX note: same as code in sp_surface.c + */ +static struct pipe_surface * +i915_get_tex_surface(struct pipe_context *pipe, +                     struct pipe_texture *pt, +                     unsigned face, unsigned level, unsigned zslice) +{ +   struct i915_texture *tex = (struct i915_texture *)pt; +   struct pipe_surface *ps; +   unsigned offset;  /* in bytes */ + +   offset = tex->level_offset[level]; + +   if (pt->target == PIPE_TEXTURE_CUBE) { +      offset += tex->image_offset[level][face] * pt->cpp; +   } +   else if (pt->target == PIPE_TEXTURE_3D) { +      offset += tex->image_offset[level][zslice] * pt->cpp; +   } +   else { +      assert(face == 0); +      assert(zslice == 0); +   } + +   ps = pipe->winsys->surface_alloc(pipe->winsys); +   if (ps) { +      assert(ps->refcount); +      assert(ps->winsys); +      pipe_buffer_reference(pipe->winsys, &ps->buffer, tex->buffer); +      ps->format = pt->format; +      ps->cpp = pt->cpp; +      ps->width = pt->width[level]; +      ps->height = pt->height[level]; +      ps->pitch = tex->pitch; +      ps->offset = offset; +   } +   return ps; +} + + + +void +i915_init_texture_functions(struct i915_context *i915) +{ +   i915->pipe.texture_create = i915_texture_create; +   i915->pipe.texture_release = i915_texture_release; +   i915->pipe.texture_update = i915_texture_update; +   i915->pipe.get_tex_surface = i915_get_tex_surface; +} diff --git a/src/gallium/drivers/i915simple/i915_texture.h b/src/gallium/drivers/i915simple/i915_texture.h index 330d111dc7..6d8d41178f 100644 --- a/src/gallium/drivers/i915simple/i915_texture.h +++ b/src/gallium/drivers/i915simple/i915_texture.h @@ -1,17 +1,38 @@ +/************************************************************************** + *  + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + *  + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *  + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *  + **************************************************************************/  #ifndef I915_TEXTURE_H  #define I915_TEXTURE_H  struct pipe_context; -struct pipe_texture; -struct pipe_texture * -i915_texture_create(struct pipe_context *pipe, -                    const struct pipe_texture *templat); -  extern void -i915_texture_release(struct pipe_context *pipe, struct pipe_texture **pt); +i915_init_texture_functions(struct i915_context *i915);  #endif /* I915_TEXTURE_H */ diff --git a/src/gallium/drivers/i965simple/Makefile b/src/gallium/drivers/i965simple/Makefile index 1dec1f9749..cc8580836c 100644 --- a/src/gallium/drivers/i965simple/Makefile +++ b/src/gallium/drivers/i965simple/Makefile @@ -1,14 +1,13 @@ -  TOP = ../../../..  include $(TOP)/configs/current  LIBNAME = i965simple -DRIVER_SOURCES = \ -        brw_blit.c \ -        brw_flush.c \ -        brw_strings.c \ -        brw_surface.c \ +C_SOURCES = \ +	brw_blit.c \ +	brw_flush.c \ +	brw_strings.c \ +	brw_surface.c \  	brw_cc.c \  	brw_clip.c \  	brw_clip_line.c \ @@ -31,8 +30,8 @@ DRIVER_SOURCES = \  	brw_sf.c \  	brw_sf_emit.c \  	brw_sf_state.c \ -        brw_shader_info.c \ -        brw_state.c \ +	brw_shader_info.c \ +	brw_state.c \  	brw_state_batch.c \  	brw_state_cache.c \  	brw_state_pool.c \ @@ -51,16 +50,6 @@ DRIVER_SOURCES = \  	brw_wm_state.c \  	brw_wm_surface_state.c -C_SOURCES = \ -	$(COMMON_SOURCES) \ -	$(COMMON_BM_SOURCES) \ -	$(MINIGLX_SOURCES) \ -	$(DRIVER_SOURCES) - -ASM_SOURCES = - -DRIVER_DEFINES = -I. -  include ../../Makefile.template  symlinks: diff --git a/src/gallium/drivers/i965simple/brw_context.c b/src/gallium/drivers/i965simple/brw_context.c index 5e58701e91..6fb840708e 100644 --- a/src/gallium/drivers/i965simple/brw_context.c +++ b/src/gallium/drivers/i965simple/brw_context.c @@ -222,10 +222,9 @@ struct pipe_context *brw_create(struct pipe_winsys *pipe_winsys,     brw->pipe.get_param = brw_get_param;     brw->pipe.get_paramf = brw_get_paramf;     brw->pipe.clear = brw_clear; -   brw->pipe.texture_create  = brw_texture_create; -   brw->pipe.texture_release = brw_texture_release;     brw_init_surface_functions(brw); +   brw_init_texture_functions(brw);     brw_init_state_functions(brw);     brw_init_flush_functions(brw);     brw_init_string_functions(brw); diff --git a/src/gallium/drivers/i965simple/brw_state.c b/src/gallium/drivers/i965simple/brw_state.c index f746d1cc57..2fc048bde0 100644 --- a/src/gallium/drivers/i965simple/brw_state.c +++ b/src/gallium/drivers/i965simple/brw_state.c @@ -32,6 +32,7 @@  #include "pipe/p_winsys.h"  #include "pipe/p_util.h" +#include "pipe/p_inlines.h"  #include "pipe/p_shader_tokens.h"  #include "tgsi/util/tgsi_dump.h" @@ -327,7 +328,9 @@ static void brw_set_sampler_texture(struct pipe_context *pipe,  {     struct brw_context *brw = brw_context(pipe); -   brw->attribs.Texture[unit] = (struct brw_texture*)texture;  /* ptr, not struct */ +   pipe_texture_reference(pipe, +                          (struct pipe_texture **) &brw->attribs.Texture[unit], +                          texture);     brw->state.dirty.brw |= BRW_NEW_TEXTURE;  } diff --git a/src/gallium/drivers/i965simple/brw_surface.c b/src/gallium/drivers/i965simple/brw_surface.c index 376a42b1a6..dc4846d39f 100644 --- a/src/gallium/drivers/i965simple/brw_surface.c +++ b/src/gallium/drivers/i965simple/brw_surface.c @@ -35,47 +35,6 @@  #include "util/p_tile.h" -/* - * XXX note: same as code in sp_surface.c - */ -static struct pipe_surface * -brw_get_tex_surface(struct pipe_context *pipe, -                     struct pipe_texture *pt, -                     unsigned face, unsigned level, unsigned zslice) -{ -   struct brw_texture *tex = (struct brw_texture *)pt; -   struct pipe_surface *ps; -   unsigned offset;  /* in bytes */ - -   offset = tex->level_offset[level]; - -   if (pt->target == PIPE_TEXTURE_CUBE) { -      offset += tex->image_offset[level][face] * pt->cpp; -   } -   else if (pt->target == PIPE_TEXTURE_3D) { -      offset += tex->image_offset[level][zslice] * pt->cpp; -   } -   else { -      assert(face == 0); -      assert(zslice == 0); -   } - -   ps = pipe->winsys->surface_alloc(pipe->winsys); -   if (ps) { -      assert(ps->format); -      assert(ps->refcount); -      pipe_buffer_reference(pipe->winsys, &ps->buffer, tex->buffer); -      ps->format = pt->format; -      ps->cpp = pt->cpp; -      ps->width = pt->width[level]; -      ps->height = pt->height[level]; -      ps->pitch = tex->pitch; -      ps->offset = offset; -   } -   return ps; -} - -  /* Upload data to a rectangular sub-region.  Lots of choices how to do this:   *   * - memcpy by span to current destination @@ -201,10 +160,10 @@ brw_surface_fill(struct pipe_context *pipe,     }  } +  void  brw_init_surface_functions(struct brw_context *brw)  { -   brw->pipe.get_tex_surface = brw_get_tex_surface;     brw->pipe.surface_copy  = brw_surface_copy;     brw->pipe.surface_fill  = brw_surface_fill;  } diff --git a/src/gallium/drivers/i965simple/brw_tex_layout.c b/src/gallium/drivers/i965simple/brw_tex_layout.c index 90561f1307..86ce3d0cc3 100644 --- a/src/gallium/drivers/i965simple/brw_tex_layout.c +++ b/src/gallium/drivers/i965simple/brw_tex_layout.c @@ -300,13 +300,15 @@ static boolean brw_miptree_layout(struct pipe_context *pipe, struct brw_texture  } -struct pipe_texture * -brw_texture_create(struct pipe_context *pipe, const struct pipe_texture *templat) +static struct pipe_texture * +brw_texture_create(struct pipe_context *pipe, +                   const struct pipe_texture *templat)  {     struct brw_texture *tex = CALLOC_STRUCT(brw_texture);     if (tex) {        tex->base = *templat; +      tex->base.refcount = 1;        if (brw_miptree_layout(pipe, tex))  	 tex->buffer = pipe->winsys->buffer_create(pipe->winsys, 64, @@ -323,7 +325,8 @@ brw_texture_create(struct pipe_context *pipe, const struct pipe_texture *templat     return &tex->base;  } -void + +static void  brw_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)  {     if (!*pt) @@ -351,3 +354,61 @@ brw_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)     }     *pt = NULL;  } + + +static void +brw_texture_update(struct pipe_context *pipe, struct pipe_texture *texture) +{ +   /* no-op? */ +} + + +/* + * XXX note: same as code in sp_surface.c + */ +static struct pipe_surface * +brw_get_tex_surface(struct pipe_context *pipe, +                     struct pipe_texture *pt, +                     unsigned face, unsigned level, unsigned zslice) +{ +   struct brw_texture *tex = (struct brw_texture *)pt; +   struct pipe_surface *ps; +   unsigned offset;  /* in bytes */ + +   offset = tex->level_offset[level]; + +   if (pt->target == PIPE_TEXTURE_CUBE) { +      offset += tex->image_offset[level][face] * pt->cpp; +   } +   else if (pt->target == PIPE_TEXTURE_3D) { +      offset += tex->image_offset[level][zslice] * pt->cpp; +   } +   else { +      assert(face == 0); +      assert(zslice == 0); +   } + +   ps = pipe->winsys->surface_alloc(pipe->winsys); +   if (ps) { +      assert(ps->format); +      assert(ps->refcount); +      pipe_buffer_reference(pipe->winsys, &ps->buffer, tex->buffer); +      ps->format = pt->format; +      ps->cpp = pt->cpp; +      ps->width = pt->width[level]; +      ps->height = pt->height[level]; +      ps->pitch = tex->pitch; +      ps->offset = offset; +   } +   return ps; +} + + +void +brw_init_texture_functions(struct brw_context *brw) +{ +   brw->pipe.texture_create  = brw_texture_create; +   brw->pipe.texture_release = brw_texture_release; +   brw->pipe.texture_update = brw_texture_update; +   brw->pipe.get_tex_surface = brw_get_tex_surface; +} diff --git a/src/gallium/drivers/i965simple/brw_tex_layout.h b/src/gallium/drivers/i965simple/brw_tex_layout.h index cfd6b1ef3a..ed49baeef8 100644 --- a/src/gallium/drivers/i965simple/brw_tex_layout.h +++ b/src/gallium/drivers/i965simple/brw_tex_layout.h @@ -1,15 +1,12 @@  #ifndef BRW_TEX_LAYOUT_H  #define BRW_TEX_LAYOUT_H -#include "pipe/p_compiler.h" -struct pipe_context; -struct pipe_texture; +struct brw_context; -extern struct pipe_texture * -brw_texture_create(struct pipe_context *pipe, const struct pipe_texture *templat);  extern void -brw_texture_release(struct pipe_context *pipe, struct pipe_texture **pt); +brw_init_texture_functions(struct brw_context *brw); +  #endif diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index 5479daf8ea..539ffb77f5 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -1,10 +1,9 @@ -  TOP = ../../../..  include $(TOP)/configs/current  LIBNAME = softpipe -DRIVER_SOURCES = \ +C_SOURCES = \  	sp_fs_exec.c \  	sp_fs_sse.c \  	sp_fs_llvm.c \ @@ -41,12 +40,6 @@ DRIVER_SOURCES = \  	sp_tile_cache.c \  	sp_surface.c  -C_SOURCES = \ -	$(COMMON_SOURCES) \ -	$(DRIVER_SOURCES) - -ASM_SOURCES =  -  include ../../Makefile.template  symlinks: diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index 5e98f190bb..2cdf3c75bf 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -283,6 +283,7 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,     /* textures */     softpipe->pipe.texture_create = softpipe_texture_create;     softpipe->pipe.texture_release = softpipe_texture_release; +   softpipe->pipe.texture_update = softpipe_texture_update;     softpipe->pipe.get_tex_surface = softpipe_get_tex_surface;     /* @@ -327,6 +328,18 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,        draw_set_rasterize_stage(softpipe->draw, softpipe->setup);     } +   /* plug in AA line/point stages */ +   draw_install_aaline_stage(softpipe->draw, &softpipe->pipe); +   draw_install_aapoint_stage(softpipe->draw, &softpipe->pipe); + +#if USE_DRAW_STAGE_PSTIPPLE +   /* Do polygon stipple w/ texture map + frag prog? */ +   draw_install_pstipple_stage(softpipe->draw, &softpipe->pipe); +#endif + +   /* sp_prim_setup can do wide points (don't convert to quads) */ +   draw_convert_wide_points(softpipe->draw, FALSE); +     sp_init_surface_functions(softpipe);     return &softpipe->pipe; diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index b70d4fea85..feeafc7084 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -39,6 +39,13 @@  #include "sp_quad.h" +/** + * This is a temporary variable for testing draw-stage polygon stipple. + * If zero, do stipple in sp_quad_stipple.c + */ +#define USE_DRAW_STAGE_PSTIPPLE 1 + +  struct softpipe_winsys;  struct softpipe_vbuf_render;  struct draw_context; @@ -68,7 +75,7 @@ struct softpipe_context {     struct pipe_framebuffer_state framebuffer;     struct pipe_poly_stipple poly_stipple;     struct pipe_scissor_state scissor; -   struct softpipe_texture *texture[PIPE_MAX_SAMPLERS]; +   struct pipe_texture *texture[PIPE_MAX_SAMPLERS];     struct pipe_viewport_state viewport;     struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];     struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX]; diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c index 9ad30a7681..8cb0534342 100644 --- a/src/gallium/drivers/softpipe/sp_fs_exec.c +++ b/src/gallium/drivers/softpipe/sp_fs_exec.c @@ -44,6 +44,41 @@ struct sp_exec_fragment_shader { +/** + * Compute quad X,Y,Z,W for the four fragments in a quad. + * + * This should really be part of the compiled shader. + */ +void +sp_setup_pos_vector(const struct tgsi_interp_coef *coef, +		    float x, float y, +		    struct tgsi_exec_vector *quadpos) +{ +   uint chan; +   /* do X */ +   quadpos->xyzw[0].f[0] = x; +   quadpos->xyzw[0].f[1] = x + 1; +   quadpos->xyzw[0].f[2] = x; +   quadpos->xyzw[0].f[3] = x + 1; + +   /* do Y */ +   quadpos->xyzw[1].f[0] = y; +   quadpos->xyzw[1].f[1] = y; +   quadpos->xyzw[1].f[2] = y + 1; +   quadpos->xyzw[1].f[3] = y + 1; + +   /* do Z and W for all fragments in the quad */ +   for (chan = 2; chan < 4; chan++) { +      const float dadx = coef->dadx[chan]; +      const float dady = coef->dady[chan]; +      const float a0 = coef->a0[chan] + dadx * x + dady * y; +      quadpos->xyzw[chan].f[0] = a0; +      quadpos->xyzw[chan].f[1] = a0 + dadx; +      quadpos->xyzw[chan].f[2] = a0 + dady; +      quadpos->xyzw[chan].f[3] = a0 + dadx + dady; +   } +} +  static void  exec_prepare( struct sp_fragment_shader *base, diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index d90066e025..8095d662ee 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -42,7 +42,7 @@  #if defined(__i386__) || defined(__386__) -#include "x86/rtasm/x86sse.h" +#include "rtasm/rtasm_x86sse.h"  /* Surely this should be defined somewhere in a tgsi header:   */ @@ -63,41 +63,6 @@ struct sp_sse_fragment_shader {  }; -/** - * Compute quad X,Y,Z,W for the four fragments in a quad. - * - * This should really be part of the compiled shader. - */ -void -sp_setup_pos_vector(const struct tgsi_interp_coef *coef, -		    float x, float y, -		    struct tgsi_exec_vector *quadpos) -{ -   uint chan; -   /* do X */ -   quadpos->xyzw[0].f[0] = x; -   quadpos->xyzw[0].f[1] = x + 1; -   quadpos->xyzw[0].f[2] = x; -   quadpos->xyzw[0].f[3] = x + 1; - -   /* do Y */ -   quadpos->xyzw[1].f[0] = y; -   quadpos->xyzw[1].f[1] = y; -   quadpos->xyzw[1].f[2] = y + 1; -   quadpos->xyzw[1].f[3] = y + 1; - -   /* do Z and W for all fragments in the quad */ -   for (chan = 2; chan < 4; chan++) { -      const float dadx = coef->dadx[chan]; -      const float dady = coef->dady[chan]; -      const float a0 = coef->a0[chan] + dadx * x + dady * y; -      quadpos->xyzw[chan].f[0] = a0; -      quadpos->xyzw[chan].f[1] = a0 + dadx; -      quadpos->xyzw[chan].f[2] = a0 + dady; -      quadpos->xyzw[chan].f[3] = a0 + dadx + dady; -   } -} -  static void  fs_sse_prepare( struct sp_fragment_shader *base, @@ -124,6 +89,9 @@ fs_sse_run( struct sp_fragment_shader *base,  		       (float)quad->x0, (float)quad->y0,   		       machine->Temps); +   /* init kill mask */ +   machine->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0] = 0x0; +     shader->func( machine->Inputs,  		 machine->Outputs,  		 machine->Consts, diff --git a/src/gallium/drivers/softpipe/sp_prim_setup.c b/src/gallium/drivers/softpipe/sp_prim_setup.c index d73521ccbe..7b1e131ee1 100644 --- a/src/gallium/drivers/softpipe/sp_prim_setup.c +++ b/src/gallium/drivers/softpipe/sp_prim_setup.c @@ -476,33 +476,33 @@ static void tri_persp_coeff( struct setup_stage *setup,   * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.   */  static void -setup_fragcoord_coeff(struct setup_stage *setup) +setup_fragcoord_coeff(struct setup_stage *setup, uint slot)  {     /*X*/ -   setup->coef[0].a0[0] = 0; -   setup->coef[0].dadx[0] = 1.0; -   setup->coef[0].dady[0] = 0.0; +   setup->coef[slot].a0[0] = 0; +   setup->coef[slot].dadx[0] = 1.0; +   setup->coef[slot].dady[0] = 0.0;     /*Y*/     if (setup->softpipe->rasterizer->origin_lower_left) {        /* y=0=bottom */        const int winHeight = setup->softpipe->framebuffer.cbufs[0]->height; -      setup->coef[0].a0[1] = (float) (winHeight - 1); -      setup->coef[0].dady[1] = -1.0; +      setup->coef[slot].a0[1] = (float) (winHeight - 1); +      setup->coef[slot].dady[1] = -1.0;     }     else {        /* y=0=top */ -      setup->coef[0].a0[1] = 0.0; -      setup->coef[0].dady[1] = 1.0; +      setup->coef[slot].a0[1] = 0.0; +      setup->coef[slot].dady[1] = 1.0;     } -   setup->coef[0].dadx[1] = 0.0; +   setup->coef[slot].dadx[1] = 0.0;     /*Z*/ -   setup->coef[0].a0[2] = setup->posCoef.a0[2]; -   setup->coef[0].dadx[2] = setup->posCoef.dadx[2]; -   setup->coef[0].dady[2] = setup->posCoef.dady[2]; +   setup->coef[slot].a0[2] = setup->posCoef.a0[2]; +   setup->coef[slot].dadx[2] = setup->posCoef.dadx[2]; +   setup->coef[slot].dady[2] = setup->posCoef.dady[2];     /*W*/ -   setup->coef[0].a0[3] = setup->posCoef.a0[3]; -   setup->coef[0].dadx[3] = setup->posCoef.dadx[3]; -   setup->coef[0].dady[3] = setup->posCoef.dady[3]; +   setup->coef[slot].a0[3] = setup->posCoef.a0[3]; +   setup->coef[slot].dadx[3] = setup->posCoef.dadx[3]; +   setup->coef[slot].dady[3] = setup->posCoef.dady[3];  } @@ -543,8 +543,7 @@ static void setup_tri_coefficients( struct setup_stage *setup )              tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);           break;        case INTERP_POS: -         assert(fragSlot == 0); -         setup_fragcoord_coeff(setup); +         setup_fragcoord_coeff(setup, fragSlot);           break;        default:           assert(0); @@ -798,9 +797,7 @@ setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim)              line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);           break;        case INTERP_POS: -         assert(fragSlot == 0); -         assert(0); /* XXX fix this: */ -         setup_fragcoord_coeff(setup); +         setup_fragcoord_coeff(setup, fragSlot);           break;        default:           assert(0); @@ -1022,9 +1019,7 @@ setup_point(struct draw_stage *stage, struct prim_header *prim)                                &setup->coef[fragSlot], vertSlot, j);           break;        case INTERP_POS: -         assert(fragSlot == 0); -         assert(0); /* XXX fix this: */ -         setup_fragcoord_coeff(setup); +         setup_fragcoord_coeff(setup, fragSlot);           break;        default:           assert(0); diff --git a/src/gallium/drivers/softpipe/sp_quad.c b/src/gallium/drivers/softpipe/sp_quad.c index 6bd468a51c..15b5594547 100644 --- a/src/gallium/drivers/softpipe/sp_quad.c +++ b/src/gallium/drivers/softpipe/sp_quad.c @@ -112,7 +112,9 @@ sp_build_quad_pipeline(struct softpipe_context *sp)        sp_push_quad_first( sp, sp->quad.earlyz );     } +#if !USE_DRAW_STAGE_PSTIPPLE     if (sp->rasterizer->poly_stipple_enable) {        sp_push_quad_first( sp, sp->quad.polygon_stipple );     } +#endif  } diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c index cf1b1eff75..2f40e09d5c 100644 --- a/src/gallium/drivers/softpipe/sp_quad_fs.c +++ b/src/gallium/drivers/softpipe/sp_quad_fs.c @@ -142,7 +142,7 @@ static void shade_begin(struct quad_stage *qs)     /* set TGSI sampler state that varies */     for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {        qss->samplers[i].state = softpipe->sampler[i]; -      qss->samplers[i].texture = &softpipe->texture[i]->base; +      qss->samplers[i].texture = softpipe->texture[i];     }     /* find output slots for depth, color */ diff --git a/src/gallium/drivers/softpipe/sp_state_clip.c b/src/gallium/drivers/softpipe/sp_state_clip.c index c797c0dd3b..4946c776e3 100644 --- a/src/gallium/drivers/softpipe/sp_state_clip.c +++ b/src/gallium/drivers/softpipe/sp_state_clip.c @@ -42,24 +42,16 @@ void softpipe_set_clip_state( struct pipe_context *pipe,  } - -/* Called when driver state tracker notices changes to the viewport - * matrix: - */  void softpipe_set_viewport_state( struct pipe_context *pipe,                                    const struct pipe_viewport_state *viewport )  {     struct softpipe_context *softpipe = softpipe_context(pipe); -   softpipe->viewport = *viewport; /* struct copy */ -   softpipe->dirty |= SP_NEW_VIEWPORT; -     /* pass the viewport info to the draw module */     draw_set_viewport_state(softpipe->draw, viewport); -   /* Using tnl/ and vf/ modules is temporary while getting started. -    * Full pipe will have vertex shader, vertex fetch of its own. -    */ +   softpipe->viewport = *viewport; /* struct copy */ +   softpipe->dirty |= SP_NEW_VIEWPORT;  } @@ -68,7 +60,9 @@ void softpipe_set_scissor_state( struct pipe_context *pipe,  {     struct softpipe_context *softpipe = softpipe_context(pipe); -   memcpy( &softpipe->scissor, scissor, sizeof(*scissor) ); +   draw_flush(softpipe->draw); + +   softpipe->scissor = *scissor; /* struct copy */     softpipe->dirty |= SP_NEW_SCISSOR;  } @@ -78,6 +72,8 @@ void softpipe_set_polygon_stipple( struct pipe_context *pipe,  {     struct softpipe_context *softpipe = softpipe_context(pipe); -   memcpy( &softpipe->poly_stipple, stipple, sizeof(*stipple) ); +   draw_flush(softpipe->draw); + +   softpipe->poly_stipple = *stipple; /* struct copy */     softpipe->dirty |= SP_NEW_STIPPLE;  } diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c index 9d8fd8b750..f9f2c5eaa8 100644 --- a/src/gallium/drivers/softpipe/sp_state_derived.c +++ b/src/gallium/drivers/softpipe/sp_state_derived.c @@ -44,7 +44,8 @@   * condition that users shouldn't hit anyway.   */  static int -find_vs_output(const struct pipe_shader_state *vs, +find_vs_output(struct softpipe_context *sp, +               const struct pipe_shader_state *vs,                 uint semantic_name,                 uint semantic_index)  { @@ -54,7 +55,9 @@ find_vs_output(const struct pipe_shader_state *vs,            vs->output_semantic_index[i] == semantic_index)           return i;     } -   return 0; + +   /* See if the draw module is introducing a new attribute... */ +   return draw_find_vs_output(sp->draw, semantic_name, semantic_index);  } @@ -111,24 +114,24 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)           int src;           switch (fs->input_semantic_name[i]) {           case TGSI_SEMANTIC_POSITION: -            src = find_vs_output(vs, TGSI_SEMANTIC_POSITION, 0); +            src = find_vs_output(softpipe, vs, TGSI_SEMANTIC_POSITION, 0);              draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_POS, src);              break;           case TGSI_SEMANTIC_COLOR: -            src = find_vs_output(vs, TGSI_SEMANTIC_COLOR,  +            src = find_vs_output(softpipe, vs, TGSI_SEMANTIC_COLOR,                                    fs->input_semantic_index[i]);              draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);              break;           case TGSI_SEMANTIC_FOG: -            src = find_vs_output(vs, TGSI_SEMANTIC_FOG, 0); +            src = find_vs_output(softpipe, vs, TGSI_SEMANTIC_FOG, 0);              draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);              break;           case TGSI_SEMANTIC_GENERIC:              /* this includes texcoords and varying vars */ -            src = find_vs_output(vs, TGSI_SEMANTIC_GENERIC, +            src = find_vs_output(softpipe, vs, TGSI_SEMANTIC_GENERIC,                                   fs->input_semantic_index[i]);              draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);              break; @@ -138,7 +141,7 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)           }        } -      softpipe->psize_slot = find_vs_output(vs, TGSI_SEMANTIC_PSIZE, 0); +      softpipe->psize_slot = find_vs_output(softpipe, vs, TGSI_SEMANTIC_PSIZE, 0);        if (softpipe->psize_slot > 0) {           draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,                                 softpipe->psize_slot); diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c index 460adccec4..18669a1c6e 100644 --- a/src/gallium/drivers/softpipe/sp_state_sampler.c +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c @@ -30,6 +30,7 @@   */  #include "pipe/p_util.h" +#include "pipe/p_inlines.h"  #include "draw/draw_context.h" @@ -82,9 +83,9 @@ softpipe_set_sampler_texture(struct pipe_context *pipe,     draw_flush(softpipe->draw);     assert(unit < PIPE_MAX_SAMPLERS); -   softpipe->texture[unit] = softpipe_texture(texture);  /* ptr, not struct */ +   pipe_texture_reference(pipe, &softpipe->texture[unit], texture); -   sp_tile_cache_set_texture(softpipe->tex_cache[unit], texture); +   sp_tile_cache_set_texture(pipe, softpipe->tex_cache[unit], texture);     softpipe->dirty |= SP_NEW_TEXTURE;  } diff --git a/src/gallium/drivers/softpipe/sp_state_surface.c b/src/gallium/drivers/softpipe/sp_state_surface.c index e2c6893e9f..124b18b708 100644 --- a/src/gallium/drivers/softpipe/sp_state_surface.c +++ b/src/gallium/drivers/softpipe/sp_state_surface.c @@ -27,7 +27,7 @@  /* Authors:  Keith Whitwell <keith@tungstengraphics.com>   */ -#include "p_inlines.h" +#include "pipe/p_inlines.h"  #include "sp_context.h"  #include "sp_state.h" diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index c54e9d385c..43d5085895 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -332,6 +332,61 @@ linear_texcoord(unsigned wrapMode, float s, unsigned size,  } +/** + * For RECT textures / unnormalized texcoords + * Only a subset of wrap modes supported. + */ +static INLINE int +nearest_texcoord_unnorm(unsigned wrapMode, float s, unsigned size) +{ +   int i; +   switch (wrapMode) { +   case PIPE_TEX_WRAP_CLAMP: +      i = ifloor(s); +      return CLAMP(i, 0, size-1); +   case PIPE_TEX_WRAP_CLAMP_TO_EDGE: +      /* fall-through */ +   case PIPE_TEX_WRAP_CLAMP_TO_BORDER: +      return ifloor( CLAMP(s, 0.5F, (float) size - 0.5F) ); +   default: +      assert(0); +      return 0; +   } +} + + +/** + * For RECT textures / unnormalized texcoords. + * Only a subset of wrap modes supported. + */ +static INLINE void +linear_texcoord_unnorm(unsigned wrapMode, float s, unsigned size, +                       int *i0, int *i1, float *a) +{ +   switch (wrapMode) { +   case PIPE_TEX_WRAP_CLAMP: +      /* Not exactly what the spec says, but it matches NVIDIA output */ +      s = CLAMP(s - 0.5F, 0.0, (float) size - 1.0); +      *i0 = ifloor(s); +      *i1 = *i0 + 1; +      break; +   case PIPE_TEX_WRAP_CLAMP_TO_EDGE: +      /* fall-through */ +   case PIPE_TEX_WRAP_CLAMP_TO_BORDER: +      s = CLAMP(s, 0.5F, (float) size - 0.5F); +      s -= 0.5F; +      *i0 = ifloor(s); +      *i1 = *i0 + 1; +      if (*i1 > size - 1) +         *i1 = size - 1; +      break; +   default: +      assert(0); +   } +   *a = FRAC(s); +} + +  static unsigned  choose_cube_face(float rx, float ry, float rz, float *newS, float *newT)  { @@ -415,15 +470,15 @@ compute_lambda(struct tgsi_sampler *sampler,  {     float rho, lambda; +   assert(sampler->state->normalized_coords); +     assert(s);     {        float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT];        float dsdy = s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT];        dsdx = FABSF(dsdx);        dsdy = FABSF(dsdy); -      rho = MAX2(dsdx, dsdy); -      if (sampler->state->normalized_coords) -         rho *= sampler->texture->width[0]; +      rho = MAX2(dsdx, dsdy) * sampler->texture->width[0];     }     if (t) {        float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]; @@ -431,9 +486,7 @@ compute_lambda(struct tgsi_sampler *sampler,        float max;        dtdx = FABSF(dtdx);        dtdy = FABSF(dtdy); -      max = MAX2(dtdx, dtdy); -      if (sampler->state->normalized_coords) -         max *= sampler->texture->height[0]; +      max = MAX2(dtdx, dtdy) * sampler->texture->height[0];        rho = MAX2(rho, max);     }     if (p) { @@ -442,9 +495,7 @@ compute_lambda(struct tgsi_sampler *sampler,        float max;        dpdx = FABSF(dpdx);        dpdy = FABSF(dpdy); -      max = MAX2(dpdx, dpdy); -      if (sampler->state->normalized_coords) -         max *= sampler->texture->depth[0]; +      max = MAX2(dpdx, dpdy) * sampler->texture->depth[0];        rho = MAX2(rho, max);     } @@ -628,13 +679,10 @@ sp_get_samples_2d_common(struct tgsi_sampler *sampler,     choose_mipmap_levels(sampler, s, t, p, lodbias,                          &level0, &level1, &levelBlend, &imgFilter); -   if (sampler->state->normalized_coords) { -      width = sampler->texture->width[level0]; -      height = sampler->texture->height[level0]; -   } -   else { -      width = height = 1; -   } +   assert(sampler->state->normalized_coords); + +   width = sampler->texture->width[level0]; +   height = sampler->texture->height[level0];     assert(width > 0); @@ -765,14 +813,11 @@ sp_get_samples_3d(struct tgsi_sampler *sampler,     choose_mipmap_levels(sampler, s, t, p, lodbias,                          &level0, &level1, &levelBlend, &imgFilter); -   if (sampler->state->normalized_coords) { -      width = sampler->texture->width[level0]; -      height = sampler->texture->height[level0]; -      depth = sampler->texture->depth[level0]; -   } -   else { -      width = height = depth = 1; -   } +   assert(sampler->state->normalized_coords); + +   width = sampler->texture->width[level0]; +   height = sampler->texture->height[level0]; +   depth = sampler->texture->depth[level0];     assert(width > 0);     assert(height > 0); @@ -889,6 +934,73 @@ sp_get_samples_cube(struct tgsi_sampler *sampler,  } +static void +sp_get_samples_rect(struct tgsi_sampler *sampler, +                    const float s[QUAD_SIZE], +                    const float t[QUAD_SIZE], +                    const float p[QUAD_SIZE], +                    float lodbias, +                    float rgba[NUM_CHANNELS][QUAD_SIZE]) +{ +   //sp_get_samples_2d_common(sampler, s, t, p, lodbias, rgba, faces); +   static const uint face = 0; +   const uint compare_func = sampler->state->compare_func; +   unsigned level0, level1, j, imgFilter; +   int width, height; +   float levelBlend; + +   choose_mipmap_levels(sampler, s, t, p, lodbias, +                        &level0, &level1, &levelBlend, &imgFilter); + +   /* texture RECTS cannot be mipmapped */ +   assert(level0 == level1); + +   width = sampler->texture->width[level0]; +   height = sampler->texture->height[level0]; + +   assert(width > 0); + +   switch (imgFilter) { +   case PIPE_TEX_FILTER_NEAREST: +      for (j = 0; j < QUAD_SIZE; j++) { +         int x = nearest_texcoord_unnorm(sampler->state->wrap_s, s[j], width); +         int y = nearest_texcoord_unnorm(sampler->state->wrap_t, t[j], height); +         get_texel(sampler, face, level0, x, y, 0, rgba, j); +         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { +            shadow_compare(compare_func, rgba, p, j); +         } +      } +      break; +   case PIPE_TEX_FILTER_LINEAR: +      for (j = 0; j < QUAD_SIZE; j++) { +         float tx[4][4], a, b; +         int x0, y0, x1, y1, c; +         linear_texcoord_unnorm(sampler->state->wrap_s, s[j], width,  &x0, &x1, &a); +         linear_texcoord_unnorm(sampler->state->wrap_t, t[j], height, &y0, &y1, &b); +         get_texel(sampler, face, level0, x0, y0, 0, tx, 0); +         get_texel(sampler, face, level0, x1, y0, 0, tx, 1); +         get_texel(sampler, face, level0, x0, y1, 0, tx, 2); +         get_texel(sampler, face, level0, x1, y1, 0, tx, 3); +         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { +            shadow_compare(compare_func, tx, p, 0); +            shadow_compare(compare_func, tx, p, 1); +            shadow_compare(compare_func, tx, p, 2); +            shadow_compare(compare_func, tx, p, 3); +         } + +         for (c = 0; c < 4; c++) { +            rgba[c][j] = lerp_2d(a, b, tx[c][0], tx[c][1], tx[c][2], tx[c][3]); +         } +      } +      break; +   default: +      assert(0); +   } +} + + + +  /**   * Called via tgsi_sampler::get_samples()   * Use the sampler's state setting to get a filtered RGBA value @@ -914,15 +1026,21 @@ sp_get_samples(struct tgsi_sampler *sampler,     switch (sampler->texture->target) {     case PIPE_TEXTURE_1D: +      assert(sampler->state->normalized_coords);        sp_get_samples_1d(sampler, s, t, p, lodbias, rgba);        break;     case PIPE_TEXTURE_2D: -      sp_get_samples_2d(sampler, s, t, p, lodbias, rgba); +      if (sampler->state->normalized_coords) +         sp_get_samples_2d(sampler, s, t, p, lodbias, rgba); +      else +         sp_get_samples_rect(sampler, s, t, p, lodbias, rgba);        break;     case PIPE_TEXTURE_3D: +      assert(sampler->state->normalized_coords);        sp_get_samples_3d(sampler, s, t, p, lodbias, rgba);        break;     case PIPE_TEXTURE_CUBE: +      assert(sampler->state->normalized_coords);        sp_get_samples_cube(sampler, s, t, p, lodbias, rgba);        break;     default: diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 6de7a9b543..6ba0f09e0a 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -39,6 +39,7 @@  #include "sp_context.h"  #include "sp_state.h"  #include "sp_texture.h" +#include "sp_tile_cache.h"  /* Simple, maximally packed layout. @@ -88,6 +89,7 @@ softpipe_texture_create(struct pipe_context *pipe,        return NULL;     spt->base = *templat; +   spt->base.refcount = 1;     softpipe_texture_layout(spt); @@ -99,6 +101,8 @@ softpipe_texture_create(struct pipe_context *pipe,        return NULL;     } +   assert(spt->base.refcount == 1); +     return &spt->base;  } @@ -128,6 +132,20 @@ softpipe_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)  } +void +softpipe_texture_update(struct pipe_context *pipe, +                        struct pipe_texture *texture) +{ +   struct softpipe_context *softpipe = softpipe_context(pipe); +   uint unit; +   for (unit = 0; unit < PIPE_MAX_SAMPLERS; unit++) { +      if (softpipe->texture[unit] == texture) { +         sp_flush_tile_cache(softpipe, softpipe->tex_cache[unit]); +      } +   } +} + +  /**   * Called via pipe->get_tex_surface()   */ diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h index fa646c0de9..50fc100427 100644 --- a/src/gallium/drivers/softpipe/sp_texture.h +++ b/src/gallium/drivers/softpipe/sp_texture.h @@ -62,6 +62,10 @@ softpipe_texture_create(struct pipe_context *pipe,  extern void  softpipe_texture_release(struct pipe_context *pipe, struct pipe_texture **pt); +extern void +softpipe_texture_update(struct pipe_context *pipe, +                        struct pipe_texture *texture); +  extern struct pipe_surface *  softpipe_get_tex_surface(struct pipe_context *pipe,                           struct pipe_texture *pt, diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index dde3fabc81..da30dd6c48 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -212,14 +212,15 @@ sp_tile_cache_unmap_surfaces(struct softpipe_tile_cache *tc)   * Specify the texture to cache.   */  void -sp_tile_cache_set_texture(struct softpipe_tile_cache *tc, +sp_tile_cache_set_texture(struct pipe_context *pipe, +                          struct softpipe_tile_cache *tc,                            struct pipe_texture *texture)  {     uint i;     assert(!tc->surface); -   tc->texture = texture; +   pipe_texture_reference(pipe, &tc->texture, texture);     if (tc->tex_surf_map) {        pipe_surface_unmap(tc->tex_surf); @@ -358,30 +359,37 @@ sp_flush_tile_cache(struct softpipe_context *softpipe,     struct pipe_surface *ps = tc->surface;     int inuse = 0, pos; -   if (!ps || !ps->buffer) -      return; - -   for (pos = 0; pos < NUM_ENTRIES; pos++) { -      struct softpipe_cached_tile *tile = tc->entries + pos; -      if (tile->x >= 0) { -         if (tc->depth_stencil) { -            pipe_put_tile_raw(pipe, ps, -                           tile->x, tile->y, TILE_SIZE, TILE_SIZE, -                           tile->data.depth32, 0/*STRIDE*/); -         } -         else { -            pipe_put_tile_rgba(pipe, ps, -                               tile->x, tile->y, TILE_SIZE, TILE_SIZE, -                               (float *) tile->data.color); +   if (ps && ps->buffer) { +      /* caching a drawing surface */ +      for (pos = 0; pos < NUM_ENTRIES; pos++) { +         struct softpipe_cached_tile *tile = tc->entries + pos; +         if (tile->x >= 0) { +            if (tc->depth_stencil) { +               pipe_put_tile_raw(pipe, ps, +                              tile->x, tile->y, TILE_SIZE, TILE_SIZE, +                              tile->data.depth32, 0/*STRIDE*/); +            } +            else { +               pipe_put_tile_rgba(pipe, ps, +                                  tile->x, tile->y, TILE_SIZE, TILE_SIZE, +                                  (float *) tile->data.color); +            } +            tile->x = tile->y = -1;  /* mark as empty */ +            inuse++;           } -         tile->x = tile->y = -1;  /* mark as empty */ -         inuse++;        } -   }  #if TILE_CLEAR_OPTIMIZATION -   sp_tile_cache_flush_clear(&softpipe->pipe, tc); +      sp_tile_cache_flush_clear(&softpipe->pipe, tc);  #endif +   } +   else if (tc->texture) { +      /* caching a texture, mark all entries as embpy */ +      for (pos = 0; pos < NUM_ENTRIES; pos++) { +         tc->entries[pos].x = -1; +      } +      tc->tex_face = -1; +   }  #if 0     debug_printf("flushed tiles in use: %d\n", inuse); diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index 7fd1081286..2631e29a3a 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -80,7 +80,8 @@ extern void  sp_tile_cache_unmap_surfaces(struct softpipe_tile_cache *tc);  extern void -sp_tile_cache_set_texture(struct softpipe_tile_cache *tc, +sp_tile_cache_set_texture(struct pipe_context *pipe, +                          struct softpipe_tile_cache *tc,                            struct pipe_texture *texture);  extern void diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 39f95695fb..036c4c8964 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -206,6 +206,14 @@ struct pipe_context {     void (*texture_release)(struct pipe_context *pipe,  			   struct pipe_texture **pt); +   /** +    * Called when texture data is changed. +    * Note: we could pass some hints about which mip levels or cube faces +    * have changed... +    */ +   void (*texture_update)(struct pipe_context *pipe, +                          struct pipe_texture *texture); +     /** Get a surface which is a "view" into a texture */     struct pipe_surface *(*get_tex_surface)(struct pipe_context *pipe,                                             struct pipe_texture *texture, diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index 3ce35310f6..10c47e0ef0 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -5,6 +5,8 @@  extern "C" {  #endif // defined __cplusplus +#include "p_compiler.h" +  struct tgsi_version  {     unsigned MajorVersion  : 8; diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 1082343e2f..47fa78c31d 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -66,7 +66,8 @@ struct pipe_winsys;   * The driver will certainly subclass this to include actual memory   * management information.   */ -struct pipe_buffer { +struct pipe_buffer +{     unsigned alignment;     unsigned usage;     unsigned size; @@ -76,8 +77,6 @@ struct pipe_buffer {  }; - -  /**   * Primitive (point/line/tri) rasterization info   */ @@ -113,18 +112,21 @@ struct pipe_rasterizer_state  }; -struct pipe_poly_stipple { +struct pipe_poly_stipple +{     unsigned stipple[32];  }; -struct pipe_viewport_state { +struct pipe_viewport_state +{     float scale[4];     float translate[4];  }; -struct pipe_scissor_state { +struct pipe_scissor_state +{     unsigned minx:16;     unsigned miny:16;     unsigned maxx:16; @@ -132,7 +134,8 @@ struct pipe_scissor_state {  }; -struct pipe_clip_state { +struct pipe_clip_state +{     float ucp[PIPE_MAX_CLIP_PLANES][4];     unsigned nr;  }; @@ -141,13 +144,15 @@ struct pipe_clip_state {  /**   * Constants for vertex/fragment shaders   */ -struct pipe_constant_buffer { +struct pipe_constant_buffer +{     struct pipe_buffer *buffer;     unsigned size;    /** in bytes */  }; -struct pipe_shader_state { +struct pipe_shader_state +{     const struct tgsi_token *tokens;     ubyte num_inputs;     ubyte num_outputs; @@ -185,7 +190,8 @@ struct pipe_depth_stencil_alpha_state  }; -struct pipe_blend_state { +struct pipe_blend_state +{     unsigned blend_enable:1;     unsigned rgb_func:3;          /**< PIPE_BLEND_x */ @@ -204,7 +210,8 @@ struct pipe_blend_state {  }; -struct pipe_blend_color { +struct pipe_blend_color +{     float color[4];  }; @@ -224,19 +231,19 @@ struct pipe_framebuffer_state   */  struct pipe_sampler_state  { -   unsigned wrap_s:3;        /**< PIPE_TEX_WRAP_x */ -   unsigned wrap_t:3;        /**< PIPE_TEX_WRAP_x */ -   unsigned wrap_r:3;        /**< PIPE_TEX_WRAP_x */ +   unsigned wrap_s:3;            /**< PIPE_TEX_WRAP_x */ +   unsigned wrap_t:3;            /**< PIPE_TEX_WRAP_x */ +   unsigned wrap_r:3;            /**< PIPE_TEX_WRAP_x */     unsigned min_img_filter:2;    /**< PIPE_TEX_FILTER_x */     unsigned min_mip_filter:2;    /**< PIPE_TEX_MIPFILTER_x */     unsigned mag_img_filter:2;    /**< PIPE_TEX_FILTER_x */ -   unsigned compare:1;       /**< shadow/depth compare enabled? */ -   unsigned compare_mode:1;  /**< PIPE_TEX_COMPARE_x */ -   unsigned compare_func:3;  /**< PIPE_FUNC_x */ -   unsigned normalized_coords:1;  /**< Are coords normalized to [0,1]? */ -   float shadow_ambient;          /**< shadow test fail color/intensity */ -   float lod_bias;                /**< LOD/lambda bias */ -   float min_lod, max_lod;        /**< LOD clamp range, after bias */ +   unsigned compare:1;           /**< shadow/depth compare enabled? */ +   unsigned compare_mode:1;      /**< PIPE_TEX_COMPARE_x */ +   unsigned compare_func:3;      /**< PIPE_FUNC_x */ +   unsigned normalized_coords:1; /**< Are coords normalized to [0,1]? */ +   float shadow_ambient;         /**< shadow test fail color/intensity */ +   float lod_bias;               /**< LOD/lambda bias */ +   float min_lod, max_lod;       /**< LOD clamp range, after bias */     float border_color[4];     float max_anisotropy;  }; @@ -248,10 +255,10 @@ struct pipe_sampler_state   */  struct pipe_surface  { -   struct pipe_buffer *buffer; /**< driver private buffer handle */ +   struct pipe_buffer *buffer;   /**< surface's buffer/memory */     enum pipe_format format;      /**< PIPE_FORMAT_x */     unsigned status;              /**< PIPE_SURFACE_STATUS_x */ -   unsigned clear_value;         /**< may be temporary */ +   unsigned clear_value;         /**< XXX may be temporary */     unsigned cpp;                 /**< bytes per pixel */     unsigned width;     unsigned height; diff --git a/src/gallium/include/pipe/p_thread.h b/src/gallium/include/pipe/p_thread.h index cd432c547c..4325abc951 100644 --- a/src/gallium/include/pipe/p_thread.h +++ b/src/gallium/include/pipe/p_thread.h @@ -1,54 +1,317 @@  /**************************************************************************   *  + * Copyright 1999-2006 Brian Paul   * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.   * All Rights Reserved.   *    * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - *  - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - *  + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + *   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.   *    **************************************************************************/ -#ifndef P_THREAD_H -#define P_THREAD_H +/** + * @file + * Thread + * + * Initial version by John Stone (j.stone@acm.org) (johns@cs.umr.edu) + *                and Christoph Poliwoda (poliwoda@volumegraphics.com) + * Revised by Keith Whitwell + * Adapted for new gl dispatcher by Brian Paul + * + * + * + * DOCUMENTATION + * + * This thread module exports the following types: + *   _glthread_TSD     Thread-specific data area + *   _glthread_Thread  Thread datatype + *   _glthread_Mutex   Mutual exclusion lock + * + * Macros: + *   _glthread_DECLARE_STATIC_MUTEX(name)   Declare a non-local mutex + *   _glthread_INIT_MUTEX(name)             Initialize a mutex + *   _glthread_LOCK_MUTEX(name)             Lock a mutex + *   _glthread_UNLOCK_MUTEX(name)           Unlock a mutex + * + * Functions: + *   _glthread_GetID(v)      Get integer thread ID + *   _glthread_InitTSD()     Initialize thread-specific data + *   _glthread_GetTSD()      Get thread-specific data + *   _glthread_SetTSD()      Set thread-specific data + * + * If this file is accidentally included by a non-threaded build, + * it should not cause the build to fail, or otherwise cause problems. + * In general, it should only be included when needed however. + */ + +#ifndef _P_THREAD_H_ +#define _P_THREAD_H_ + + +#if defined(USE_MGL_NAMESPACE) +#define _glapi_Dispatch _mglapi_Dispatch +#endif + + + +#if (defined(PTHREADS) || defined(SOLARIS_THREADS) ||\ +     defined(WIN32_THREADS) || defined(USE_XTHREADS) || defined(BEOS_THREADS)) \ +    && !defined(THREADS) +# define THREADS +#endif + +#ifdef VMS +#include <GL/vms_x_fix.h> +#endif + +/* + * POSIX threads. This should be your choice in the Unix world + * whenever possible.  When building with POSIX threads, be sure + * to enable any compiler flags which will cause the MT-safe + * libc (if one exists) to be used when linking, as well as any + * header macros for MT-safe errno, etc.  For Solaris, this is the -mt + * compiler flag.  On Solaris with gcc, use -D_REENTRANT to enable + * proper compiling for MT-safe libc etc. + */ +#if defined(PTHREADS) +#include <pthread.h> /* POSIX threads headers */ + +typedef struct { +   pthread_key_t  key; +   int initMagic; +} _glthread_TSD; + +typedef pthread_t _glthread_Thread; + +typedef pthread_mutex_t _glthread_Mutex; + +#define _glthread_DECLARE_STATIC_MUTEX(name) \ +   static _glthread_Mutex name = PTHREAD_MUTEX_INITIALIZER + +#define _glthread_INIT_MUTEX(name) \ +   pthread_mutex_init(&(name), NULL) + +#define _glthread_DESTROY_MUTEX(name) \ +   pthread_mutex_destroy(&(name)) + +#define _glthread_LOCK_MUTEX(name) \ +   (void) pthread_mutex_lock(&(name)) + +#define _glthread_UNLOCK_MUTEX(name) \ +   (void) pthread_mutex_unlock(&(name)) + +#endif /* PTHREADS */ + + + + +/* + * Solaris threads. Use only up to Solaris 2.4. + * Solaris 2.5 and higher provide POSIX threads. + * Be sure to compile with -mt on the Solaris compilers, or + * use -D_REENTRANT if using gcc. + */ +#ifdef SOLARIS_THREADS +#include <thread.h> + +typedef struct { +   thread_key_t key; +   mutex_t      keylock; +   int          initMagic; +} _glthread_TSD; + +typedef thread_t _glthread_Thread; + +typedef mutex_t _glthread_Mutex; + +/* XXX need to really implement mutex-related macros */ +#define _glthread_DECLARE_STATIC_MUTEX(name)  static _glthread_Mutex name = 0 +#define _glthread_INIT_MUTEX(name)  (void) name +#define _glthread_DESTROY_MUTEX(name) (void) name +#define _glthread_LOCK_MUTEX(name)  (void) name +#define _glthread_UNLOCK_MUTEX(name)  (void) name + +#endif /* SOLARIS_THREADS */ + + + + +/* + * Windows threads. Should work with Windows NT and 95. + * IMPORTANT: Link with multithreaded runtime library when THREADS are + * used! + */ +#ifdef WIN32_THREADS +#include <windows.h> + +typedef struct { +   DWORD key; +   int   initMagic; +} _glthread_TSD; + +typedef HANDLE _glthread_Thread; + +typedef CRITICAL_SECTION _glthread_Mutex; + +#define _glthread_DECLARE_STATIC_MUTEX(name)  /*static*/ _glthread_Mutex name = {0,0,0,0,0,0} +#define _glthread_INIT_MUTEX(name)  InitializeCriticalSection(&name) +#define _glthread_DESTROY_MUTEX(name)  DeleteCriticalSection(&name) +#define _glthread_LOCK_MUTEX(name)  EnterCriticalSection(&name) +#define _glthread_UNLOCK_MUTEX(name)  LeaveCriticalSection(&name) + +#endif /* WIN32_THREADS */ + + -#include "p_compiler.h"  /* - * XXX: We should come up with a system-independent thread definitions. - * XXX: Patching glthread defs for now. + * XFree86 has its own thread wrapper, Xthreads.h + * We wrap it again for GL.   */ +#ifdef USE_XTHREADS +#include <X11/Xthreads.h> + +typedef struct { +   xthread_key_t key; +   int initMagic; +} _glthread_TSD; + +typedef xthread_t _glthread_Thread; + +typedef xmutex_rec _glthread_Mutex; + +#ifdef XMUTEX_INITIALIZER +#define _glthread_DECLARE_STATIC_MUTEX(name) \ +   static _glthread_Mutex name = XMUTEX_INITIALIZER +#else +#define _glthread_DECLARE_STATIC_MUTEX(name) \ +   static _glthread_Mutex name +#endif + +#define _glthread_INIT_MUTEX(name) \ +   xmutex_init(&(name)) + +#define _glthread_DESTROY_MUTEX(name) \ +   xmutex_clear(&(name)) + +#define _glthread_LOCK_MUTEX(name) \ +   (void) xmutex_lock(&(name)) + +#define _glthread_UNLOCK_MUTEX(name) \ +   (void) xmutex_unlock(&(name)) + +#endif /* USE_XTHREADS */ + + + +/* + * BeOS threads. R5.x required. + */ +#ifdef BEOS_THREADS + +#include <kernel/OS.h> +#include <support/TLS.h> + +typedef struct { +   int32        key; +   int          initMagic; +} _glthread_TSD; + +typedef thread_id _glthread_Thread; + +/* Use Benaphore, aka speeder semaphore */ +typedef struct { +    int32   lock; +    sem_id  sem; +} benaphore; +typedef benaphore _glthread_Mutex; + +#define _glthread_DECLARE_STATIC_MUTEX(name)  static _glthread_Mutex name = { 0, 0 } +#define _glthread_INIT_MUTEX(name)    	name.sem = create_sem(0, #name"_benaphore"), name.lock = 0 +#define _glthread_DESTROY_MUTEX(name) 	delete_sem(name.sem), name.lock = 0 +#define _glthread_LOCK_MUTEX(name)    	if (name.sem == 0) _glthread_INIT_MUTEX(name); \ +									  	if (atomic_add(&(name.lock), 1) >= 1) acquire_sem(name.sem) +#define _glthread_UNLOCK_MUTEX(name)  	if (atomic_add(&(name.lock), -1) > 1) release_sem(name.sem) + +#endif /* BEOS_THREADS */ + + + +#ifndef THREADS + +/* + * THREADS not defined + */ + +typedef unsigned _glthread_TSD; + +typedef unsigned _glthread_Thread; + +typedef unsigned _glthread_Mutex; + +#define _glthread_DECLARE_STATIC_MUTEX(name)  static _glthread_Mutex name = 0 + +#define _glthread_INIT_MUTEX(name)  (void) name + +#define _glthread_DESTROY_MUTEX(name)  (void) name + +#define _glthread_LOCK_MUTEX(name)  (void) name + +#define _glthread_UNLOCK_MUTEX(name)  (void) name + +#endif /* THREADS */ + + + +/* + * Platform independent thread specific data API. + */ + +extern unsigned long +_glthread_GetID(void); + + +extern void +_glthread_InitTSD(_glthread_TSD *); + + +extern void * +_glthread_GetTSD(_glthread_TSD *); -#ifndef __MSC__ -#include "glapi/glthread.h" +extern void +_glthread_SetTSD(_glthread_TSD *, void *); -#else /* __MSC__ */ +#if defined(GLX_USE_TLS) -typedef int _glthread_Mutex; +extern __thread struct _glapi_table * _glapi_tls_Dispatch +    __attribute__((tls_model("initial-exec"))); -#define _glthread_INIT_MUTEX( M )   ((void) (M)) -#define _glthread_LOCK_MUTEX( M )   ((void) (M)) -#define _glthread_UNLOCK_MUTEX( M ) ((void) (M)) +#define GET_DISPATCH() _glapi_tls_Dispatch -#define sched_yield() ((void) 0) +#elif !defined(GL_CALL) +# if defined(THREADS) +#  define GET_DISPATCH() \ +   ((__builtin_expect( _glapi_Dispatch != NULL, 1 )) \ +       ? _glapi_Dispatch : _glapi_get_dispatch()) +# else +#  define GET_DISPATCH() _glapi_Dispatch +# endif /* defined(THREADS) */ +#endif  /* ndef GL_CALL */ -#endif /* __MSC__ */ -#endif /* P_THREAD_H */ +#endif /* _P_THREAD_H_ */ diff --git a/src/gallium/winsys/Makefile b/src/gallium/winsys/Makefile new file mode 100644 index 0000000000..3dc5ea5744 --- /dev/null +++ b/src/gallium/winsys/Makefile @@ -0,0 +1,20 @@ +TOP = ../../.. +include $(TOP)/configs/current + + +SUBDIRS = $(GALLIUM_WINSYS_DIRS) + + +default: subdirs + + +subdirs: +	@for dir in $(SUBDIRS) ; do \ +		if [ -d $$dir ] ; then \ +			(cd $$dir && $(MAKE)) || exit 1 ; \ +		fi \ +	done + + +clean: +	rm -f `find . -name \*.[oa]` diff --git a/src/gallium/winsys/SConscript b/src/gallium/winsys/SConscript new file mode 100644 index 0000000000..32215d8d58 --- /dev/null +++ b/src/gallium/winsys/SConscript @@ -0,0 +1,10 @@ +Import('*') + +if dri: +	SConscript([ +		'dri/SConscript', +	]) +else: +	SConscript([ +		'xlib/SConscript', +	]) diff --git a/src/gallium/winsys/dri/Makefile.template b/src/gallium/winsys/dri/Makefile.template index 2a261ed669..3bc1fdd4d4 100644 --- a/src/gallium/winsys/dri/Makefile.template +++ b/src/gallium/winsys/dri/Makefile.template @@ -1,7 +1,9 @@  # -*-makefile-*- -MESA_MODULES = $(TOP)/src/mesa/libmesa.a - +MESA_MODULES = \ +	$(TOP)/src/mesa/libmesa.a \ +	$(GALLIUM_AUXILIARIES) +	  COMMON_GALLIUM_SOURCES = \          $(TOP)/src/mesa/drivers/dri/common/utils.c \          $(TOP)/src/mesa/drivers/dri/common/vblank.c \ @@ -23,8 +25,9 @@ WINOBJ=  WINLIB=  INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES) -OBJECTS = $(C_SOURCES:.c=.o) \ -	  $(ASM_SOURCES:.S=.o)  +OBJECTS = \ +	$(C_SOURCES:.c=.o) \ +	$(ASM_SOURCES:.S=.o)   else  # miniglx diff --git a/src/mesa/drivers/dri/SConscript b/src/gallium/winsys/dri/SConscript index d32bd08669..8c56ce917c 100644 --- a/src/mesa/drivers/dri/SConscript +++ b/src/gallium/winsys/dri/SConscript @@ -6,6 +6,9 @@ drienv.Replace(CPPPATH = [  	'#src/mesa/drivers/dri/common',  	'#include',  	'#include/GL/internal', +	'#src/gallium/include', +	'#src/gallium/auxiliary', +	'#src/gallium/drivers',  	'#src/mesa',  	'#src/mesa/main',  	'#src/mesa/glapi', @@ -21,15 +24,15 @@ drienv.Replace(CPPPATH = [  drienv.ParseConfig('pkg-config --cflags --libs libdrm')  COMMON_GALLIUM_SOURCES = [ -	'../common/utils.c', -	'../common/vblank.c', -	'../common/dri_util.c', -	'../common/xmlconfig.c', +	'#src/mesa/drivers/dri/common/utils.c', +	'#src/mesa/drivers/dri/common/vblank.c', +	'#src/mesa/drivers/dri/common/dri_util.c', +	'#src/mesa/drivers/dri/common/xmlconfig.c',  ]  COMMON_BM_SOURCES = [ -	'../common/dri_bufmgr.c', -	'../common/dri_drmpool.c', +	'#src/mesa/drivers/dri/common/dri_bufmgr.c', +	'#src/mesa/drivers/dri/common/dri_drmpool.c',  ]  Export([ @@ -44,5 +47,5 @@ Export([  #	$(INSTALL) -m 755 $(LIBNAME) $(DRI_DRIVER_INSTALL_DIR)  SConscript([ -	'intel_winsys/SConscript', +	'intel/SConscript',  ]) diff --git a/src/gallium/winsys/dri/intel/SConscript b/src/gallium/winsys/dri/intel/SConscript index a7cc10450e..0ad19d42a8 100644 --- a/src/gallium/winsys/dri/intel/SConscript +++ b/src/gallium/winsys/dri/intel/SConscript @@ -9,11 +9,6 @@ env.Append(CPPPATH = [  #MINIGLX_SOURCES = server/intel_dri.c -pipe_drivers = [ -	softpipe, -	i915simple -] -  DRIVER_SOURCES = [  	'intel_winsys_pipe.c',  	'intel_winsys_softpipe.c', @@ -31,11 +26,14 @@ sources = \  	COMMON_BM_SOURCES + \  	DRIVER_SOURCES -# DRIVER_DEFINES = -I../intel $(shell pkg-config libdrm --atleast-version=2.3.1 \ -#				&& echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP") +drivers = [ +	softpipe, +	i915simple +] +# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions  env.SharedLibrary(  	target ='i915tex_dri.so',  	source = sources, -	LIBS = pipe_drivers + env['LIBS'], +	LIBS = drivers + mesa + auxiliaries + env['LIBS'],  )
\ No newline at end of file diff --git a/src/gallium/winsys/dri/intel/intel_batchpool.c b/src/gallium/winsys/dri/intel/intel_batchpool.c index 33b56817f6..ce154c7b88 100644 --- a/src/gallium/winsys/dri/intel/intel_batchpool.c +++ b/src/gallium/winsys/dri/intel/intel_batchpool.c @@ -36,9 +36,12 @@  #include <xf86drm.h>  #include <stdlib.h> +#include <stdio.h>  #include <errno.h> -#include "imports.h" -#include "glthread.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_thread.h" +  #include "dri_bufpool.h"  #include "dri_bufmgr.h"  #include "intel_batchpool.h" @@ -196,7 +199,7 @@ pool_create(struct _DriBufferPool *pool,     _glthread_LOCK_MUTEX(p->mutex);     if (p->numFree == 0) -      pool_checkFree(p, GL_TRUE); +      pool_checkFree(p, TRUE);     if (p->numFree == 0) {        fprintf(stderr, "Out of fixed size buffer objects\n"); @@ -278,7 +281,7 @@ pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,        return -EBUSY;     } -   buf->mapped = GL_TRUE; +   buf->mapped = TRUE;     *virtual = (unsigned char *) p->virtual + buf->start;     _glthread_UNLOCK_MUTEX(p->mutex);     return 0; @@ -361,7 +364,7 @@ pool_validate(struct _DriBufferPool *pool, void *private)     BBuf *buf = (BBuf *) private;     BPool *p = buf->parent;     _glthread_LOCK_MUTEX(p->mutex); -   buf->unfenced = GL_TRUE; +   buf->unfenced = TRUE;     _glthread_UNLOCK_MUTEX(p->mutex);     return 0;  } @@ -379,7 +382,7 @@ pool_takedown(struct _DriBufferPool *pool)     while ((p->numFree < p->numTot) && p->numDelayed) {        _glthread_UNLOCK_MUTEX(p->mutex);        sched_yield(); -      pool_checkFree(p, GL_TRUE); +      pool_checkFree(p, TRUE);        _glthread_LOCK_MUTEX(p->mutex);     } diff --git a/src/gallium/winsys/xlib/Makefile b/src/gallium/winsys/xlib/Makefile new file mode 100644 index 0000000000..c443330942 --- /dev/null +++ b/src/gallium/winsys/xlib/Makefile @@ -0,0 +1,93 @@ +# src/gallium/winsys/xlib/Makefile + +TOP = ../../../.. +include $(TOP)/configs/current + + +GL_MAJOR = 1 +GL_MINOR = 5 +GL_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY) + + +INCLUDE_DIRS = \ +	-I$(TOP)/include \ +	-I$(TOP)/src/mesa \ +	-I$(TOP)/src/mesa/main \ +	-I$(TOP)/src/gallium/include \ +	-I$(TOP)/src/gallium/drivers \ +	-I$(TOP)/src/gallium/auxiliary + +XLIB_WINSYS_SOURCES = \ +	glxapi.c	\ +	fakeglx.c	\ +	xfonts.c	\ +	xm_api.c	\ +	xm_winsys.c	\ +	xm_winsys_aub.c	\ +	brw_aub.c + +XLIB_WINSYS_OBJECTS = $(XLIB_WINSYS_SOURCES:.c=.o) + + +ifeq ($(CONFIG_NAME), linux-cell) +# The SPU code is in a separate .a file, unfortunately +CELL_SPU_LIB = $(TOP)/src/gallium/drivers/cell/spu/g3d_spu.a +endif + +LIBS = \ +	$(GALLIUM_DRIVERS) \ +	$(TOP)/src/mesa/libglapi.a \ +	$(TOP)/src/mesa/libmesa.a \ +	$(GALLIUM_AUXILIARIES) \ +	$(CELL_SPU_LIB) \ + + +.SUFFIXES : .cpp + +.c.o: +	$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ + +.cpp.o: +	$(CXX) -c $(INCLUDE_DIRS) $(CXXFLAGS) $< -o $@ + + + +default: $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) + + +# Make the libGL.so library +$(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(XLIB_WINSYS_OBJECTS) $(LIBS) +	$(TOP)/bin/mklib -o $(GL_LIB) \ +		-linker "$(CC)" \ +		-major $(GL_MAJOR) -minor $(GL_MINOR) -patch $(GL_TINY) \ +		-install $(TOP)/$(LIB_DIR) \ +		$(MKLIB_OPTIONS) $(XLIB_WINSYS_OBJECTS) \ +		--start-group $(LIBS) --end-group $(GL_LIB_DEPS) + + +depend: $(ALL_SOURCES) +	@ echo "running $(MKDEP)" +	@ rm -f depend  # workaround oops on gutsy?!? +	@ touch depend +	@ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \ +		> /dev/null 2>/dev/null + + +install: default +	$(INSTALL) -d $(INSTALL_DIR)/include/GL +	$(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR) +	$(INSTALL) -m 644 $(TOP)/include/GL/*.h $(INSTALL_DIR)/include/GL +	@if [ -e $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ]; then \ +		$(INSTALL) $(TOP)/$(LIB_DIR)/libGL* $(INSTALL_DIR)/$(LIB_DIR); \ +	fi + + +# Emacs tags +tags: +	etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h + +clean: +	-rm -f *.o + + +include depend diff --git a/src/gallium/winsys/xlib/SConscript b/src/gallium/winsys/xlib/SConscript new file mode 100644 index 0000000000..c38b5be52c --- /dev/null +++ b/src/gallium/winsys/xlib/SConscript @@ -0,0 +1,34 @@ +####################################################################### +# SConscript for xlib winsys + +Import('*') + +env = env.Clone() + +env.Append(CPPPATH = [ +	'#/src/mesa', +	'#/src/mesa/main', +]) + +sources = [ +	'glxapi.c', +	'fakeglx.c', +	'xfonts.c', +	'xm_api.c', +	'xm_winsys.c', +	'xm_winsys_aub.c', +	'brw_aub.c', +] +	 +drivers = [ +	softpipe, +	i915simple, +	i965simple, +] + +# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions +env.SharedLibrary( +	target ='GL', +	source = sources, +	LIBS = glapi + mesa + drivers + auxiliaries + env['LIBS'], +) diff --git a/src/gallium/winsys/xlib/brw_aub.c b/src/gallium/winsys/xlib/brw_aub.c index 541d50c6e4..10eedd8402 100644 --- a/src/gallium/winsys/xlib/brw_aub.c +++ b/src/gallium/winsys/xlib/brw_aub.c @@ -29,11 +29,13 @@    *   Keith Whitwell <keith@tungstengraphics.com>    */ +#include <stdio.h> +#include <stdlib.h>  #include "brw_aub.h"  #include "pipe/p_context.h"  #include "pipe/p_state.h" -#include "imports.h" -//#include "intel_winsys.h" +#include "pipe/p_util.h" +#include "pipe/p_debug.h"  struct brw_aubfile { @@ -350,9 +352,9 @@ struct brw_aubfile *brw_aubfile_create( void )     i++; -   if (_mesa_getenv("INTEL_AUBFILE")) { -      val = snprintf(filename, sizeof(filename), "%s%d.aub", _mesa_getenv("INTEL_AUBFILE"), i%4); -      _mesa_printf("--> Aub file: %s\n", filename); +   if (getenv("INTEL_AUBFILE")) { +      val = snprintf(filename, sizeof(filename), "%s%d.aub", getenv("INTEL_AUBFILE"), i%4); +      debug_printf("--> Aub file: %s\n", filename);        aubfile->file = fopen(filename, "w");     }     else { @@ -360,12 +362,12 @@ struct brw_aubfile *brw_aubfile_create( void )        if (val < 0 || val > sizeof(filename))   	 strcpy(filename, "default.aub");    -      _mesa_printf("--> Aub file: %s\n", filename); +      debug_printf("--> Aub file: %s\n", filename);        aubfile->file = fopen(filename, "w");     }     if (!aubfile->file) { -      _mesa_printf("couldn't open aubfile\n"); +      debug_printf("couldn't open aubfile\n");        exit(1);     } diff --git a/src/glx/x11/Makefile b/src/glx/x11/Makefile index 5f74fcff06..b404727f08 100644 --- a/src/glx/x11/Makefile +++ b/src/glx/x11/Makefile @@ -35,7 +35,7 @@ SOURCES = \  include $(TOP)/src/mesa/sources -MESA_ASM_API = $(addprefix $(TOP)/src/mesa/, $(ASM_API)) +MESA_GLAPI_ASM_SOURCES = $(addprefix $(TOP)/src/mesa/, $(GLAPI_ASM_SOURCES))  MESA_GLAPI_SOURCES = $(addprefix $(TOP)/src/mesa/, $(GLAPI_SOURCES))  MESA_GLAPI_OBJECTS = $(addprefix $(TOP)/src/mesa/, $(GLAPI_OBJECTS)) @@ -70,11 +70,11 @@ $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME):  $(OBJECTS) Makefile  		-install $(TOP)/$(LIB_DIR) $(GL_LIB_DEPS) $(OBJECTS) -depend: $(SOURCES) $(MESA_GLAPI_SOURCES) $(MESA_ASM_API) Makefile +depend: $(SOURCES) $(MESA_GLAPI_SOURCES) $(MESA_GLAPI_ASM_SOURCES) Makefile  	rm -f depend  	touch depend  	$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES) \ -		$(MESA_GLAPI_SOURCES) $(MESA_ASM_API)  +		$(MESA_GLAPI_SOURCES) $(MESA_GLAPI_ASM_SOURCES)   # Emacs tags diff --git a/src/mesa/Makefile b/src/mesa/Makefile index c8cb2b592f..2403223db2 100644 --- a/src/mesa/Makefile +++ b/src/mesa/Makefile @@ -11,19 +11,6 @@ GL_MINOR = 5  GL_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY) -PIPE_LIB = \ -	$(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ -	$(TOP)/src/gallium/drivers/i965simple/libi965simple.a - -ifeq ($(CONFIG_NAME), linux-cell) -CELL_LIB = $(TOP)/src/gallium/drivers/cell/ppu/libcell.a -CELL_LIB_SPU = $(TOP)/src/gallium/drivers/cell/spu/g3d_spu.a -endif - -ifeq ($(CONFIG_NAME), linux-llvm) -LLVM_LIB = $(TOP)/src/gallium/auxiliary/llvm/libgallivm.a -endif -  .SUFFIXES : .cpp  .c.o: @@ -36,33 +23,14 @@ endif  	$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ -# Figure out what to make here -default: -	@if [ "${DRIVER_DIRS}" = "dri" ] ; then \ -		$(MAKE) linux-solo ; \ -	elif [ "${DRIVER_DIRS}" = "osmesa" ] ; then \ -		$(MAKE) osmesa-only ; \ -	elif [ "$(DRIVER_DIRS)" = "beos" ]; then \ -		$(MAKE) beos ; \ -	elif [ "$(DRIVER_DIRS)" = "directfb" ]; then \ -		$(MAKE) directfb ; \ -	elif [ "$(DRIVER_DIRS)" = "fbdev osmesa" ]; then \ -		$(MAKE) fbdev ; $(MAKE) osmesa-only ; \ -	else \ -		$(MAKE) stand-alone ; \ -	fi - +default: depend subdirs libmesa.a -###################################################################### -# BeOS driver target - -beos: depend subdirs libmesa.a -	cd drivers/beos; $(MAKE) +ifneq ($(DRIVER_DIRS),dri) +default: libglapi.a +endif  ###################################################################### -# Linux DRI drivers -  # Make archive of core object files  libmesa.a: $(SOLO_OBJECTS)  	@ $(TOP)/bin/mklib -o mesa -static $(SOLO_OBJECTS); @@ -70,32 +38,8 @@ libmesa.a: $(SOLO_OBJECTS)  		mimeset -f "$@" ; \  	fi -linux-solo: depend subdirs libmesa.a -	cd $(TOP)/src/gallium/winsys/dri ; $(MAKE) - - -##################################################################### -# Stand-alone Mesa libGL, no built-in drivers (DirectFB) - -libgl-core: $(CORE_OBJECTS) -	@ $(TOP)/bin/mklib -o $(GL_LIB) \ -		-major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \ -		-install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) $(CORE_OBJECTS) \ -		$(GL_LIB_DEPS) - -directfb: depend subdirs libgl-core -	cd drivers/directfb ; $(MAKE) - - -##################################################################### -# fbdev Mesa driver (libGL.so) - -fbdev: $(CORE_OBJECTS) $(FBDEV_DRIVER_OBJECTS) $(COMMON_DRIVER_OBJECTS) -	@ $(TOP)/bin/mklib -o $(GL_LIB) \ -		-major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \ -		-install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \ -		$(CORE_OBJECTS) $(FBDEV_DRIVER_OBJECTS) \ -		$(COMMON_DRIVER_OBJECTS) $(GL_LIB_DEPS) +libglapi.a: $(GLAPI_OBJECTS) +	@ $(TOP)/bin/mklib -o glapi -static $(GLAPI_OBJECTS)  ###################################################################### @@ -123,13 +67,13 @@ stand-alone: depend subdirs $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$  osmesa-only: depend subdirs $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME)  # Make the GL library -$(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(STAND_ALONE_OBJECTS) $(PIPE_LIB) $(CELL_LIB) $(CELL_LIB_SPU) $(LLVM_LIB) +$(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(STAND_ALONE_OBJECTS) $(PIPE_LIB) $(CELL_LIB) $(CELL_LIB_SPU)  	@ $(TOP)/bin/mklib -o $(GL_LIB) \  		-linker "$(CC)" \  		-major $(GL_MAJOR) -minor $(GL_MINOR) -patch $(GL_TINY) \  		-install $(TOP)/$(LIB_DIR) \  		$(MKLIB_OPTIONS) $(STAND_ALONE_OBJECTS) \ -		$(PIPE_LIB) $(CELL_LIB) $(CELL_LIB_SPU) $(LLVM_LIB) $(GL_LIB_DEPS) +		$(PIPE_LIB) $(CELL_LIB) $(CELL_LIB_SPU) $(GL_LIB_DEPS)  # Make the OSMesa library  $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME): $(OSMESA_DRIVER_OBJECTS) \ @@ -176,9 +120,6 @@ install: default  	@if [ -e $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME) ]; then \  		$(INSTALL) $(TOP)/$(LIB_DIR)/libOSMesa* $(INSTALL_DIR)/$(LIB_DIR); \  	fi -	@if [ "${DRIVER_DIRS}" = "dri" ] ; then \ -		cd $(TOP)/gallium/winsys/dri ; $(MAKE) install ; \ -	fi  ## NOT INSTALLED YET:  ## $(INSTALL) -d $(INSTALL_DIR)/include/GLES @@ -192,9 +133,8 @@ tags:  clean:  	-rm -f */*.o  	-rm -f */*/*.o -	-rm -f depend depend.bak libmesa.a +	-rm -f depend depend.bak libmesa.a libglapi.a  	-rm -f drivers/*/*.o -	(cd drivers/dri && $(MAKE) clean)  	(cd x86 && $(MAKE) clean)  	(cd x86-64 && $(MAKE) clean) diff --git a/src/mesa/SConscript b/src/mesa/SConscript index faf8c84872..db18c61fac 100644 --- a/src/mesa/SConscript +++ b/src/mesa/SConscript @@ -1,11 +1,16 @@  ####################################################################### -# SConscript for mesa -# -# TODO: Split this into per-module SConscripts  +# SConscript for Mesa  Import('*') +env = env.Clone() + +# Includes +env.Append(CPPPATH = [ +	'#/src/mesa', +	'#/src/mesa/main', +])  #######################################################################  # Core sources @@ -116,53 +121,6 @@ VF_SOURCES = [  	'vf/vf_sse.c',  ] -DRAW_SOURCES = [ -	'pipe/draw/draw_clip.c', -	'pipe/draw/draw_context.c', -	'pipe/draw/draw_cull.c', -	'pipe/draw/draw_debug.c', -	'pipe/draw/draw_flatshade.c', -	'pipe/draw/draw_offset.c', -	'pipe/draw/draw_prim.c', -	'pipe/draw/draw_stipple.c', -	'pipe/draw/draw_twoside.c', -	'pipe/draw/draw_unfilled.c', -	'pipe/draw/draw_validate.c', -	'pipe/draw/draw_vbuf.c', -	'pipe/draw/draw_vertex.c', -	'pipe/draw/draw_vertex_cache.c', -	'pipe/draw/draw_vertex_fetch.c', -	'pipe/draw/draw_vertex_shader.c', -	'pipe/draw/draw_vertex_shader_llvm.c', -	'pipe/draw/draw_vf.c', -	'pipe/draw/draw_vf_generic.c', -	'pipe/draw/draw_vf_sse.c', -	'pipe/draw/draw_wide_prims.c', -] - -TGSIEXEC_SOURCES = [ -	'pipe/tgsi/exec/tgsi_exec.c', -	'pipe/tgsi/exec/tgsi_sse2.c', -] - -TGSIUTIL_SOURCES = [ -	'pipe/tgsi/util/tgsi_build.c', -	'pipe/tgsi/util/tgsi_dump.c', -	'pipe/tgsi/util/tgsi_parse.c', -	'pipe/tgsi/util/tgsi_util.c', -] - -STATECACHE_SOURCES = [ -	'pipe/cso_cache/cso_hash.c', -	'pipe/cso_cache/cso_cache.c', -] - -PIPEUTIL_SOURCES = [ -	'pipe/util/p_debug.c', -	'pipe/util/p_tile.c', -	'pipe/util/p_util.c', -] -  STATETRACKER_SOURCES = [  	'state_tracker/st_atom.c',  	'state_tracker/st_atom_blend.c', @@ -311,126 +269,25 @@ else:  	ASM_SOURCES = []  	API_SOURCES = [] - -####################################################################### -# Driver sources - - -X11_DRIVER_SOURCES = [ -	'pipe/xlib/glxapi.c', -	'pipe/xlib/fakeglx.c', -	'pipe/xlib/xfonts.c', -	'pipe/xlib/xm_api.c', -	'pipe/xlib/xm_winsys.c', -	'pipe/xlib/xm_winsys_aub.c', -	'pipe/xlib/brw_aub.c', -] - -OSMESA_DRIVER_SOURCES = [ -	'drivers/osmesa/osmesa.c', -] - -GLIDE_DRIVER_SOURCES = [ -	'drivers/glide/fxapi.c', -	'drivers/glide/fxdd.c', -	'drivers/glide/fxddspan.c', -	'drivers/glide/fxddtex.c', -	'drivers/glide/fxsetup.c', -	'drivers/glide/fxtexman.c', -	'drivers/glide/fxtris.c', -	'drivers/glide/fxvb.c', -	'drivers/glide/fxglidew.c', -	'drivers/glide/fxg.c', -] - -SVGA_DRIVER_SOURCES = [ -	'drivers/svga/svgamesa.c', -	'drivers/svga/svgamesa8.c', -	'drivers/svga/svgamesa15.c', -	'drivers/svga/svgamesa16.c', -	'drivers/svga/svgamesa24.c', -	'drivers/svga/svgamesa32.c', -] - -FBDEV_DRIVER_SOURCES = [ -	'drivers/fbdev/glfbdev.c', -] - - -### All the core C sources -  SOLO_SOURCES = \  	MAIN_SOURCES + \  	MATH_SOURCES + \  	VBO_SOURCES + \  	VF_SOURCES + \ -	DRAW_SOURCES + \ -	TGSIEXEC_SOURCES + \ -	TGSIUTIL_SOURCES + \ -	PIPEUTIL_SOURCES + \ -	STATECACHE_SOURCES + \  	STATETRACKER_SOURCES + \  	SHADER_SOURCES + \  	ASM_SOURCES + \  	SLANG_SOURCES -CORE_SOURCES = \ -	GLAPI_SOURCES + API_SOURCES + \ -	SOLO_SOURCES - -ALL_SOURCES = \ -	GLAPI_SOURCES + API_SOURCES + \ -	SOLO_SOURCES + \ -	ASM_SOURCES + \ -	X11_DRIVER_SOURCES + \ -	FBDEV_DRIVER_SOURCES + \ -	OSMESA_DRIVER_SOURCES - - -###################################################################### -# Gallium sources - -SConscript([ -	'pipe/SConscript', -]) - - -###################################################################### -# libGL +mesa = env.ConvenienceLibrary( +	target = 'mesa', +	source = SOLO_SOURCES, +) +Export('mesa')  if not dri: -	STAND_ALONE_DRIVER_SOURCES = \ -		CORE_SOURCES + \ -		X11_DRIVER_SOURCES -	 -	Import( -		'softpipe',  -		'i915simple', -		'i965simple' -	) -	 -	pipe_drivers = [ -		softpipe, -		i965simple -	] -	 -	env.SharedLibrary( -		target ='GL', -		source = STAND_ALONE_DRIVER_SOURCES, -		LIBS = [softpipe, i965simple] + env['LIBS'], +	glapi = env.ConvenienceLibrary( +		target = 'glapi', +		source = GLAPI_SOURCES + API_SOURCES,  	) - - -###################################################################### -# Driver sources - -if dri: -	mesa = env.ConvenienceLibrary( -		target = 'mesa', -		source = SOLO_SOURCES, -	) -	env.Prepend(LIBS = [mesa]) - -	SConscript([ -		'drivers/dri/SConscript', -	]) +	Export('glapi') diff --git a/src/mesa/sources b/src/mesa/sources index f83d247a1e..f0bf7b31fb 100644 --- a/src/mesa/sources +++ b/src/mesa/sources @@ -156,51 +156,6 @@ VF_SOURCES = \  	vf/vf_generic.c \  	vf/vf_sse.c - -DRAW_SOURCES = \ -	$(TOP)/src/gallium/auxiliary/draw/draw_clip.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vs_exec.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vs_sse.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vs_llvm.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_context.c\ -	$(TOP)/src/gallium/auxiliary/draw/draw_cull.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_debug.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_flatshade.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_offset.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_prim.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_stipple.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_twoside.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_unfilled.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_validate.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vbuf.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vertex.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vertex_cache.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vertex_fetch.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vertex_shader.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vf.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vf_generic.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_vf_sse.c \ -	$(TOP)/src/gallium/auxiliary/draw/draw_wide_prims.c - -TGSIEXEC_SOURCES = \ -	$(TOP)/src/gallium/auxiliary/tgsi/exec/tgsi_exec.c \ -	$(TOP)/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c - -TGSIUTIL_SOURCES = \ -	$(TOP)/src/gallium/auxiliary/tgsi/util/tgsi_build.c \ -	$(TOP)/src/gallium/auxiliary/tgsi/util/tgsi_dump.c \ -	$(TOP)/src/gallium/auxiliary/tgsi/util/tgsi_parse.c \ -	$(TOP)/src/gallium/auxiliary/tgsi/util/tgsi_util.c - -STATECACHE_SOURCES = \ -	$(TOP)/src/gallium/auxiliary/cso_cache/cso_hash.c \ -	$(TOP)/src/gallium/auxiliary/cso_cache/cso_cache.c - -PIPEUTIL_SOURCES = \ -	$(TOP)/src/gallium/auxiliary/util/p_debug.c \ -	$(TOP)/src/gallium/auxiliary/util/p_tile.c \ -	$(TOP)/src/gallium/auxiliary/util/p_util.c -  STATETRACKER_SOURCES = \  	state_tracker/st_atom.c \  	state_tracker/st_atom_blend.c \ @@ -229,7 +184,7 @@ STATETRACKER_SOURCES = \  	state_tracker/st_cb_readpixels.c \  	state_tracker/st_cb_strings.c \  	state_tracker/st_cb_texture.c \ -        state_tracker/st_cache.c \ +	state_tracker/st_cache.c \  	state_tracker/st_context.c \  	state_tracker/st_debug.c \  	state_tracker/st_draw.c \ @@ -291,7 +246,6 @@ ASM_C_SOURCES =	\  	x86/rtasm/x86sse.c \  	sparc/sparc.c \  	ppc/common_ppc.c \ -	ppc/rtasm/spe_asm.c \  	x86-64/x86-64.c  X86_SOURCES =			\ @@ -333,15 +287,6 @@ SPARC_API =			\  __COMMON_DRIVER_SOURCES =			\  	drivers/common/driverfuncs.c -X11_DRIVER_SOURCES =		\ -	$(TOP)/src/gallium/winsys/xlib/glxapi.c	\ -	$(TOP)/src/gallium/winsys/xlib/fakeglx.c	\ -	$(TOP)/src/gallium/winsys/xlib/xfonts.c	\ -	$(TOP)/src/gallium/winsys/xlib/xm_api.c	\ -	$(TOP)/src/gallium/winsys/xlib/xm_winsys.c	\ -	$(TOP)/src/gallium/winsys/xlib/xm_winsys_aub.c	\ -	$(TOP)/src/gallium/winsys/xlib/brw_aub.c -  OSMESA_DRIVER_SOURCES = \  	drivers/osmesa/osmesa.c @@ -374,7 +319,7 @@ FBDEV_DRIVER_SOURCES =			\  ALL_SOURCES = \  	$(GLAPI_SOURCES)	\  	$(SOLO_SOURCES)		\ -	$(ASM_SOURCES)		\ +	$(MESA_ASM_SOURCES)		\  	$(COMMON_DRIVER_SOURCES)\  	$(X11_DRIVER_SOURCES)	\  	$(FBDEV_DRIVER_SOURCES) \ @@ -407,11 +352,11 @@ CORE_SOURCES = \  SOLO_OBJECTS = \  	$(SOLO_SOURCES:.c=.o) \ -	$(ASM_SOURCES:.S=.o) +	$(MESA_ASM_SOURCES:.S=.o)  GLAPI_OBJECTS = \  	$(GLAPI_SOURCES:.c=.o) \ -	$(ASM_API:.S=.o) +	$(GLAPI_ASM_SOURCES:.S=.o)  CORE_OBJECTS = $(SOLO_OBJECTS) $(GLAPI_OBJECTS) diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 2a836d630b..a4ac726816 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -34,6 +34,7 @@  #include "st_context.h"  #include "st_atom.h" +#include "st_texture.h"  #include "st_cb_texture.h"  #include "pipe/p_context.h" @@ -53,28 +54,33 @@ update_textures(struct st_context *st)     for (unit = 0; unit < st->ctx->Const.MaxTextureCoordUnits; unit++) {        const GLuint su = fprog->Base.SamplerUnits[unit];        struct gl_texture_object *texObj = st->ctx->Texture.Unit[su]._Current; -      struct pipe_texture *pt; +      struct st_texture_object *stObj = st_texture_object(texObj);        if (texObj) {           GLboolean flush, retval;           retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);           /* XXX retval indicates whether there's a texture border */ - -         pt = st_get_texobj_texture(texObj); -      } -      else { -         pt = NULL;        }        /* XXX: need to ensure that textures are unbound/removed from         * this table before being deleted, otherwise the pointer         * comparison below could fail.         */ -      if (st->state.sampler_texture[unit] != pt) { -	 st->state.sampler_texture[unit] = pt; -	 st->pipe->set_sampler_texture(st->pipe, unit, pt); +      if (st->state.sampler_texture[unit] != stObj) { +         struct pipe_texture *pt = st_get_stobj_texture(stObj); +         st->state.sampler_texture[unit] = stObj; +         st->pipe->set_sampler_texture(st->pipe, unit, pt); +      } + +      stObj = st->state.sampler_texture[unit]; + +      if (stObj && stObj->dirtyData) { +         struct pipe_texture *pt = st_get_stobj_texture(stObj); +         st->pipe->texture_update(st->pipe, pt); +         stObj->dirtyData = GL_FALSE;        } +     }  } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index e2d4e06da1..585cae3743 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -726,7 +726,8 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,     pipe->bind_rasterizer_state(pipe, ctx->st->state.rasterizer->data);     pipe->bind_fs_state(pipe, ctx->st->state.fs->data);     pipe->bind_vs_state(pipe, ctx->st->state.vs->cso->data); -   pipe->set_sampler_texture(pipe, unit, ctx->st->state.sampler_texture[unit]); +   pipe->set_sampler_texture(pipe, unit, +                st_get_stobj_texture(ctx->st->state.sampler_texture[unit]));     pipe->bind_sampler_state(pipe, unit, ctx->st->state.sampler[unit]->data);     pipe->set_viewport_state(pipe, &ctx->st->state.viewport);  } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 4341623267..781425b546 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -48,6 +48,7 @@  #include "st_cb_texture.h"  #include "st_format.h"  #include "st_public.h" +#include "st_texture.h" diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 03dbb30b0f..778fb536bc 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -53,33 +53,6 @@  #define DBG if (0) printf -struct st_texture_object -{ -   struct gl_texture_object base;       /* The "parent" object */ - -   /* The texture must include at levels [0..lastLevel] once validated: -    */ -   GLuint lastLevel; - -   /* On validation any active images held in main memory or in other -    * textures will be copied to this texture and the old storage freed. -    */ -   struct pipe_texture *pt; - -   GLboolean imageOverride; -   GLint depthOverride; -   GLuint pitchOverride; -}; - - - -static INLINE struct st_texture_object * -st_texture_object(struct gl_texture_object *obj) -{ -   return (struct st_texture_object *) obj; -} - -  static INLINE struct st_texture_image *  st_texture_image(struct gl_texture_image *img)  { @@ -87,14 +60,6 @@ st_texture_image(struct gl_texture_image *img)  } -struct pipe_texture * -st_get_texobj_texture(struct gl_texture_object *texObj) -{ -   struct st_texture_object *stObj = st_texture_object(texObj); -   return stObj->pt; -} - -  static enum pipe_texture_target  gl_target_to_pipe(GLenum target)  { @@ -725,11 +690,12 @@ st_TexImage(GLcontext * ctx,        texImage->Data = NULL;     } -#if 01 +   /* flag data as dirty */ +   stObj->dirtyData = GL_TRUE; +     if (level == texObj->BaseLevel && texObj->GenerateMipmap) {        ctx->Driver.GenerateMipmap(ctx, target, texObj);     } -#endif  } @@ -900,6 +866,7 @@ st_TexSubimage(GLcontext * ctx,                   struct gl_texture_object *texObj,                   struct gl_texture_image *texImage)  { +   struct st_texture_object *stObj = st_texture_object(texObj);     struct st_texture_image *stImage = st_texture_image(texImage);     GLuint dstRowStride;     GLuint srcImageStride = _mesa_image_image_stride(packing, width, height, @@ -946,14 +913,9 @@ st_TexSubimage(GLcontext * ctx,        }     } -#if 0 -   /* GL_SGIS_generate_mipmap */     if (level == texObj->BaseLevel && texObj->GenerateMipmap) { -      _mesa_generate_mipmap(ctx, target, -                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit], -                            texObj); +      ctx->Driver.GenerateMipmap(ctx, target, texObj);     } -#endif     _mesa_unmap_teximage_pbo(ctx, packing); @@ -961,6 +923,9 @@ st_TexSubimage(GLcontext * ctx,        st_texture_image_unmap(stImage);        texImage->Data = NULL;     } + +   /* flag data as dirty */ +   stObj->dirtyData = GL_TRUE;  } @@ -1126,6 +1091,7 @@ do_copy_texsubimage(GLcontext *ctx,     struct gl_texture_image *texImage =        _mesa_select_tex_image(ctx, texObj, target, level);     struct st_texture_image *stImage = st_texture_image(texImage); +   struct st_texture_object *stObj = st_texture_object(texObj);     GLenum baseFormat = texImage->InternalFormat;     struct gl_framebuffer *fb = ctx->ReadBuffer;     struct st_renderbuffer *strb; @@ -1212,17 +1178,12 @@ do_copy_texsubimage(GLcontext *ctx,     pipe_surface_reference(&dest_surface, NULL); -#if 0 -   /* GL_SGIS_generate_mipmap -- this can be accelerated now. -    * XXX Add a ctx->Driver.GenerateMipmaps() function? -    */ +   /* flag data as dirty */ +   stObj->dirtyData = GL_TRUE; +     if (level == texObj->BaseLevel && texObj->GenerateMipmap) { -      intel_generate_mipmap(ctx, target, -                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit], -                            texObj); +      ctx->Driver.GenerateMipmap(ctx, target, texObj);     } -#endif -  } diff --git a/src/mesa/state_tracker/st_cb_texture.h b/src/mesa/state_tracker/st_cb_texture.h index 878256ec26..843745fcd6 100644 --- a/src/mesa/state_tracker/st_cb_texture.h +++ b/src/mesa/state_tracker/st_cb_texture.h @@ -1,9 +1,33 @@ -#ifndef ST_CB_TEXTURE_H -#define ST_CB_TEXTURE_H +/************************************************************************** + *  + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + *  + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *  + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *  + **************************************************************************/ -extern struct pipe_texture * -st_get_texobj_texture(struct gl_texture_object *texObj); +#ifndef ST_CB_TEXTURE_H +#define ST_CB_TEXTURE_H  extern GLboolean diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 59d1590f05..5be4769be4 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -59,26 +59,6 @@ struct st_tracked_state { -struct st_texture_image -{ -   struct gl_texture_image base; - -   /* These aren't stored in gl_texture_image  -    */ -   GLuint level; -   GLuint face; - -   /* If stImage->pt != NULL, image data is stored here. -    * Else if stImage->base.Data != NULL, image is stored there. -    * Else there is no image data. -    */ -   struct pipe_texture *pt; - -   struct pipe_surface *surface; -}; - - -  struct st_context  {     GLcontext *ctx; @@ -106,7 +86,7 @@ struct st_context        struct pipe_clip_state clip;        struct pipe_constant_buffer constants[2];        struct pipe_framebuffer_state framebuffer; -      struct pipe_texture *sampler_texture[PIPE_MAX_SAMPLERS]; +      struct st_texture_object *sampler_texture[PIPE_MAX_SAMPLERS];        struct pipe_poly_stipple poly_stipple;        struct pipe_scissor_state scissor;        struct pipe_viewport_state viewport; diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index 6c09b86033..c9765b2003 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -43,6 +43,7 @@  #include "st_draw.h"  #include "st_gen_mipmap.h"  #include "st_program.h" +#include "st_texture.h"  #include "st_cb_drawpixels.h"  #include "st_cb_texture.h" @@ -110,14 +111,22 @@ st_init_generate_mipmap(struct st_context *st)     struct pipe_rasterizer_state rasterizer;     struct pipe_depth_stencil_alpha_state depthstencil; +   /* we don't use blending, but need to set valid values */     memset(&blend, 0, sizeof(blend)); +   blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; +   blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; +   blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; +   blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;     blend.colormask = PIPE_MASK_RGBA;     st->gen_mipmap.blend_cso = pipe->create_blend_state(pipe, &blend);     memset(&depthstencil, 0, sizeof(depthstencil));     st->gen_mipmap.depthstencil_cso = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil); +   /* Note: we're assuming zero is valid for all non-specified fields */     memset(&rasterizer, 0, sizeof(rasterizer)); +   rasterizer.front_winding = PIPE_WINDING_CW; +   rasterizer.cull_mode = PIPE_WINDING_NONE;     st->gen_mipmap.rasterizer_cso = pipe->create_rasterizer_state(pipe, &rasterizer);     st->gen_mipmap.stfp = make_tex_fragment_program(st->ctx); @@ -302,7 +311,8 @@ st_render_mipmap(struct st_context *st,        pipe->bind_vs_state(pipe, st->state.vs->cso->data);     if (st->state.sampler[0])        pipe->bind_sampler_state(pipe, 0, st->state.sampler[0]->data); -   pipe->set_sampler_texture(pipe, 0, st->state.sampler_texture[0]); +   pipe->set_sampler_texture(pipe, 0, +                        st_get_stobj_texture(st->state.sampler_texture[0]));     pipe->set_viewport_state(pipe, &st->state.viewport);     return TRUE; diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index ea1dde4a7a..25cf3e94a8 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -36,7 +36,6 @@  #include "mtypes.h"  #include "pipe/p_shader_tokens.h" -#include "x86/rtasm/x86sse.h"  #define ST_MAX_SHADER_TOKENS 1024 diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index b86f416c9b..ad284170e4 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -76,7 +76,7 @@ st_texture_create(struct st_context *st,  		  GLuint depth0,  		  GLuint compress_byte)  { -   struct pipe_texture pt; +   struct pipe_texture pt, *newtex;     assert(target <= PIPE_TEXTURE_CUBE); @@ -95,9 +95,12 @@ st_texture_create(struct st_context *st,     pt.depth[0] = depth0;     pt.compressed = compress_byte ? 1 : 0;     pt.cpp = pt.compressed ? compress_byte : st_sizeof_format(format); -   pt.refcount = 1;  -   return st->pipe->texture_create(st->pipe, &pt); +   newtex = st->pipe->texture_create(st->pipe, &pt); + +   assert(!newtex || newtex->refcount == 1); + +   return newtex;  } diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index 72324cd9ab..78f5f451ed 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -35,6 +35,70 @@ struct pipe_context;  struct pipe_texture; +struct st_texture_image +{ +   struct gl_texture_image base; + +   /* These aren't stored in gl_texture_image  +    */ +   GLuint level; +   GLuint face; + +   /* If stImage->pt != NULL, image data is stored here. +    * Else if stImage->base.Data != NULL, image is stored there. +    * Else there is no image data. +    */ +   struct pipe_texture *pt; + +   struct pipe_surface *surface; +}; + + + +struct st_texture_object +{ +   struct gl_texture_object base;       /* The "parent" object */ + +   /* The texture must include at levels [0..lastLevel] once validated: +    */ +   GLuint lastLevel; + +   /* On validation any active images held in main memory or in other +    * textures will be copied to this texture and the old storage freed. +    */ +   struct pipe_texture *pt; + +   GLboolean imageOverride; +   GLint depthOverride; +   GLuint pitchOverride; + +   GLboolean dirtyData; +}; + + +static INLINE struct st_texture_object * +st_texture_object(struct gl_texture_object *obj) +{ +   return (struct st_texture_object *) obj; +} + + +static INLINE struct pipe_texture * +st_get_texobj_texture(struct gl_texture_object *texObj) +{ +   struct st_texture_object *stObj = st_texture_object(texObj); +   return stObj ? stObj->pt : NULL; +} + + +static INLINE struct pipe_texture * +st_get_stobj_texture(struct st_texture_object *stObj) +{ +   return stObj ? stObj->pt : NULL; +} + + +  extern struct pipe_texture *  st_texture_create(struct st_context *st,                    enum pipe_texture_target target, diff --git a/src/mesa/x86/common_x86_asm.S b/src/mesa/x86/common_x86_asm.S index ef3cc9eb59..09c86b05ba 100644 --- a/src/mesa/x86/common_x86_asm.S +++ b/src/mesa/x86/common_x86_asm.S @@ -39,7 +39,7 @@   * in there will break the build on some platforms.   */ -#include "matypes.h" +#include "assyntax.h"  #include "common_x86_features.h"  	SEG_TEXT  | 
